2006-04-23 06:44:19 +00:00
|
|
|
/*
|
|
|
|
* Playing-field leveller for Build
|
|
|
|
* by Jonathon Fowler
|
|
|
|
*
|
|
|
|
* A note about this:
|
|
|
|
* 1. There is some kind of problem somewhere in the functions below because
|
|
|
|
* compiling with __compat_h_macrodef__ disabled makes stupid things happen.
|
|
|
|
* 2. The functions below, aside from the ones which aren't trivial, were never
|
|
|
|
* really intended to be used for anything except tracking anr removing ties
|
|
|
|
* to the standard C library from games. Using the Bxx versions of functions
|
|
|
|
* means we can redefine those names to link up with different runtime library
|
|
|
|
* names.
|
|
|
|
*/
|
|
|
|
|
2014-11-24 06:30:47 +00:00
|
|
|
#include "compat.h"
|
|
|
|
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2014-11-24 06:30:47 +00:00
|
|
|
# include <shlobj.h>
|
|
|
|
# include <direct.h>
|
2014-12-08 04:31:57 +00:00
|
|
|
#elif __APPLE__
|
|
|
|
# include "osxbits.h"
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
|
2009-07-09 02:29:48 +00:00
|
|
|
#if defined(_MSC_VER)
|
2006-04-23 06:44:19 +00:00
|
|
|
# include <io.h>
|
|
|
|
#else
|
|
|
|
# include <dirent.h>
|
|
|
|
#endif
|
|
|
|
|
2015-03-02 07:54:24 +00:00
|
|
|
#if defined __linux || defined EDUKE32_BSD
|
2014-12-08 04:31:57 +00:00
|
|
|
# include <libgen.h> // for dirname()
|
|
|
|
#endif
|
2016-06-06 22:13:05 +00:00
|
|
|
#if defined EDUKE32_BSD
|
2015-03-02 07:54:24 +00:00
|
|
|
# include <limits.h> // for PATH_MAX
|
2014-12-08 04:31:57 +00:00
|
|
|
# include <sys/sysctl.h> // for sysctl() to get path to executable
|
|
|
|
#endif
|
|
|
|
|
2010-01-16 20:17:33 +00:00
|
|
|
#include "baselayer.h"
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2014-05-30 00:02:16 +00:00
|
|
|
////////// PANICKING ALLOCATION FUNCTIONS //////////
|
|
|
|
|
|
|
|
static void (*g_MemErrHandler)(int32_t line, const char *file, const char *func);
|
|
|
|
|
|
|
|
#ifdef DEBUGGINGAIDS
|
|
|
|
static const char *g_MemErrFunc = "???";
|
|
|
|
static const char *g_MemErrFile = "???";
|
|
|
|
static int32_t g_MemErrLine;
|
|
|
|
|
|
|
|
void xalloc_set_location(int32_t line, const char *file, const char *func)
|
|
|
|
{
|
|
|
|
g_MemErrLine = line;
|
|
|
|
g_MemErrFile = file;
|
|
|
|
|
|
|
|
if (func)
|
|
|
|
g_MemErrFunc = func;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-09-30 04:12:27 +00:00
|
|
|
void handle_memerr(void)
|
2014-05-30 00:02:16 +00:00
|
|
|
{
|
2014-09-30 04:12:27 +00:00
|
|
|
if (g_MemErrHandler)
|
2014-05-30 00:02:16 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUGGINGAIDS
|
2014-09-30 04:12:27 +00:00
|
|
|
g_MemErrHandler(g_MemErrLine, g_MemErrFile, g_MemErrFunc);
|
2014-05-30 00:02:16 +00:00
|
|
|
#else
|
2014-09-30 04:12:27 +00:00
|
|
|
g_MemErrHandler(0, "???", "???");
|
2014-05-30 00:02:16 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-30 04:12:27 +00:00
|
|
|
Bexit(EXIT_FAILURE);
|
2014-05-30 00:02:16 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:12:27 +00:00
|
|
|
void set_memerr_handler(void(*handlerfunc)(int32_t, const char *, const char *))
|
2014-05-30 00:02:16 +00:00
|
|
|
{
|
2014-09-30 04:12:27 +00:00
|
|
|
g_MemErrHandler = handlerfunc;
|
2014-05-30 00:02:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////
|
|
|
|
|
2014-11-22 12:32:56 +00:00
|
|
|
#ifndef compat_h_macrodef__
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
void Bassert(int expr) { assert(expr); }
|
|
|
|
int32_t Brand(void) { return rand(); }
|
|
|
|
void *Bmalloc(bsize_t size) { return malloc(size); }
|
2015-09-23 17:55:31 +00:00
|
|
|
void Bfree(void *ptr) { free(ptr); }
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2009-06-05 20:09:13 +00:00
|
|
|
int32_t Bopen(const char *pathname, int32_t flags, uint32_t mode)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
int32_t n = 0, o = 0;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
if (flags & BO_BINARY)
|
|
|
|
n |= O_BINARY;
|
|
|
|
else
|
|
|
|
n |= O_TEXT;
|
|
|
|
if ((flags & BO_RDWR) == BO_RDWR)
|
|
|
|
n |= O_RDWR;
|
|
|
|
else if ((flags & BO_RDWR) == BO_WRONLY)
|
|
|
|
n |= O_WRONLY;
|
|
|
|
else if ((flags & BO_RDWR) == BO_RDONLY)
|
|
|
|
n |= O_RDONLY;
|
|
|
|
if (flags & BO_APPEND)
|
|
|
|
n |= O_APPEND;
|
|
|
|
if (flags & BO_CREAT)
|
|
|
|
n |= O_CREAT;
|
|
|
|
if (flags & BO_TRUNC)
|
|
|
|
n |= O_TRUNC;
|
|
|
|
if (mode & BS_IREAD)
|
|
|
|
o |= S_IREAD;
|
|
|
|
if (mode & BS_IWRITE)
|
|
|
|
o |= S_IWRITE;
|
|
|
|
if (mode & BS_IEXEC)
|
|
|
|
o |= S_IEXEC;
|
|
|
|
|
|
|
|
return open(pathname, n, o);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t Bclose(int32_t fd) { return close(fd); }
|
|
|
|
bssize_t Bwrite(int32_t fd, const void *buf, bsize_t count) { return write(fd, buf, count); }
|
|
|
|
bssize_t Bread(int32_t fd, void *buf, bsize_t count) { return read(fd, buf, count); }
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Blseek(int32_t fildes, int32_t offset, int32_t whence)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2007-12-12 17:42:14 +00:00
|
|
|
switch (whence)
|
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
case BSEEK_SET: whence = SEEK_SET; break;
|
|
|
|
case BSEEK_CUR: whence = SEEK_CUR; break;
|
|
|
|
case BSEEK_END: whence = SEEK_END; break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-01-11 04:53:30 +00:00
|
|
|
return lseek(fildes, offset, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
BFILE *Bfopen(const char *path, const char *mode) { return (BFILE *)fopen(path, mode); }
|
|
|
|
int32_t Bfclose(BFILE *stream) { return fclose((FILE *)stream); }
|
|
|
|
void Brewind(BFILE *stream) { rewind((FILE *)stream); }
|
|
|
|
int32_t Bfgetc(BFILE *stream) { return fgetc((FILE *)stream); }
|
|
|
|
char *Bfgets(char *s, int32_t size, BFILE *stream) { return fgets(s, size, (FILE *)stream); }
|
|
|
|
int32_t Bfputc(int32_t c, BFILE *stream) { return fputc(c, (FILE *)stream); }
|
|
|
|
int32_t Bfputs(const char *s, BFILE *stream) { return fputs(s, (FILE *)stream); }
|
|
|
|
bsize_t Bfread(void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fread(ptr, size, nmemb, (FILE *)stream); }
|
|
|
|
bsize_t Bfwrite(const void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fwrite(ptr, size, nmemb, (FILE *)stream); }
|
|
|
|
char *Bstrdup(const char *s) { return strdup(s); }
|
|
|
|
char *Bstrcpy(char *dest, const char *src) { return strcpy(dest, src); }
|
|
|
|
char *Bstrncpy(char *dest, const char *src, bsize_t n) { return Bstrncpy(dest, src, n); }
|
|
|
|
int32_t Bstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); }
|
|
|
|
int32_t Bstrncmp(const char *s1, const char *s2, bsize_t n) { return strncmp(s1, s2, n); }
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bstrcasecmp(const char *s1, const char *s2)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
return _stricmp(s1, s2);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
return strcasecmp(s1, s2);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bstrncasecmp(const char *s1, const char *s2, bsize_t n)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
return _strnicmp(s1, s2, n);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
return strncasecmp(s1, s2, n);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *Bstrcat(char *dest, const char *src) { return strcat(dest, src); }
|
|
|
|
char *Bstrncat(char *dest, const char *src, bsize_t n) { return strncat(dest, src, n); }
|
|
|
|
bsize_t Bstrlen(const char *s) { return strlen(s); }
|
|
|
|
char *Bstrchr(const char *s, int32_t c) { return strchr(s, c); }
|
|
|
|
char *Bstrrchr(const char *s, int32_t c) { return strrchr(s, c); }
|
|
|
|
int32_t Batoi(const char *nptr) { return strtol(nptr, NULL, 10); }
|
|
|
|
int32_t Batol(const char *nptr) { return strtol(nptr, NULL, 10); }
|
|
|
|
int32_t Bstrtol(const char *nptr, char **endptr, int32_t base) { return strtol(nptr, endptr, base); }
|
|
|
|
uint32_t Bstrtoul(const char *nptr, char **endptr, int32_t base) { return strtoul(nptr, endptr, base); }
|
|
|
|
void *Bmemcpy(void *dest, const void *src, bsize_t n) { return memcpy(dest, src, n); }
|
|
|
|
void *Bmemmove(void *dest, const void *src, bsize_t n) { return memmove(dest, src, n); }
|
|
|
|
void *Bmemchr(const void *s, int32_t c, bsize_t n) { return memchr(s, c, n); }
|
|
|
|
void *Bmemset(void *s, int32_t c, bsize_t n) { return memset(s, c, n); }
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bprintf(const char *format, ...)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
va_list ap;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
va_start(ap, format);
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
r = _vprintf(format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
r = vprintf(format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
va_end(ap);
|
|
|
|
return r;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bsprintf(char *str, const char *format, ...)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
va_list ap;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
va_start(ap, format);
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
r = _vsprintf(str, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
r = vsprintf(str, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
va_end(ap);
|
|
|
|
return r;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bsnprintf(char *str, bsize_t size, const char *format, ...)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
va_list ap;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
va_start(ap, format);
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
r = _vsnprintf(str, size, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
r = vsnprintf(str, size, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
va_end(ap);
|
|
|
|
return r;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bvsnprintf(char *str, bsize_t size, const char *format, va_list ap)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
return _vsnprintf(str, size, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
return vsnprintf(str, size, format, ap);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *Bgetenv(const char *name) { return getenv(name); }
|
|
|
|
char *Bgetcwd(char *buf, bsize_t size) { return getcwd(buf, size); }
|
2006-04-23 06:44:19 +00:00
|
|
|
|
|
|
|
#endif // __compat_h_macrodef__
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Stuff which must be a function
|
|
|
|
//
|
2012-11-05 02:49:08 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
typedef BOOL (WINAPI * aSHGetSpecialFolderPathAtype)(HWND, LPTSTR, int, BOOL);
|
|
|
|
#endif
|
2006-04-23 06:44:19 +00:00
|
|
|
|
|
|
|
char *Bgethomedir(void)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2012-11-05 02:49:08 +00:00
|
|
|
aSHGetSpecialFolderPathAtype aSHGetSpecialFolderPathA;
|
2006-04-24 19:04:22 +00:00
|
|
|
TCHAR appdata[MAX_PATH];
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t loaded = 0;
|
2008-08-23 03:12:23 +00:00
|
|
|
HMODULE hShell32 = GetModuleHandle("shell32.dll");
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2008-08-23 03:12:23 +00:00
|
|
|
if (hShell32 == NULL)
|
|
|
|
{
|
|
|
|
hShell32 = LoadLibrary("shell32.dll");
|
|
|
|
loaded = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hShell32 == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2012-11-05 02:49:08 +00:00
|
|
|
aSHGetSpecialFolderPathA = (aSHGetSpecialFolderPathAtype)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
|
2008-03-07 21:59:10 +00:00
|
|
|
if (aSHGetSpecialFolderPathA != NULL)
|
|
|
|
if (SUCCEEDED(aSHGetSpecialFolderPathA(NULL, appdata, CSIDL_APPDATA, FALSE)))
|
2008-08-23 03:12:23 +00:00
|
|
|
{
|
|
|
|
if (loaded)
|
|
|
|
FreeLibrary(hShell32);
|
2009-10-07 06:47:35 +00:00
|
|
|
return Bstrdup(appdata);
|
2008-08-23 03:12:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (loaded)
|
|
|
|
FreeLibrary(hShell32);
|
2006-04-24 19:04:22 +00:00
|
|
|
return NULL;
|
2015-02-14 07:26:10 +00:00
|
|
|
#elif defined EDUKE32_OSX
|
2014-12-08 04:31:57 +00:00
|
|
|
return osx_gethomedir();
|
2012-05-01 12:40:08 +00:00
|
|
|
#elif defined(GEKKO)
|
|
|
|
// return current drive's name
|
|
|
|
char *drv, cwd[BMAX_PATH] = {0};
|
|
|
|
getcwd(cwd, BMAX_PATH);
|
|
|
|
drv = strchr(cwd, ':');
|
|
|
|
if (drv)
|
|
|
|
drv[1] = '\0';
|
|
|
|
return Bstrdup(cwd);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
char *e = getenv("HOME");
|
|
|
|
if (!e) return NULL;
|
2009-10-07 06:47:35 +00:00
|
|
|
return Bstrdup(e);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:31:57 +00:00
|
|
|
char *Bgetappdir(void)
|
|
|
|
{
|
|
|
|
char *dir = NULL;
|
2014-12-08 07:32:58 +00:00
|
|
|
|
2014-12-08 04:31:57 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
TCHAR appdir[MAX_PATH];
|
2014-12-08 07:32:58 +00:00
|
|
|
|
2014-12-08 04:31:57 +00:00
|
|
|
if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) {
|
|
|
|
// trim off the filename
|
2015-01-11 04:53:30 +00:00
|
|
|
char *slash = Bstrrchr(appdir, '\\');
|
2014-12-08 04:31:57 +00:00
|
|
|
if (slash) slash[0] = 0;
|
2015-01-11 04:53:30 +00:00
|
|
|
dir = Bstrdup(appdir);
|
2014-12-08 04:31:57 +00:00
|
|
|
}
|
|
|
|
|
2015-02-14 07:26:10 +00:00
|
|
|
#elif defined EDUKE32_OSX
|
2014-12-08 04:31:57 +00:00
|
|
|
dir = osx_getappdir();
|
2015-03-02 07:54:24 +00:00
|
|
|
#elif defined __FreeBSD__
|
|
|
|
// the sysctl should also work when /proc/ is not mounted (which seems to
|
|
|
|
// be common on FreeBSD), so use it..
|
|
|
|
char buf[PATH_MAX] = {0};
|
|
|
|
int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
|
|
|
|
size_t len = sizeof(buf)-1;
|
|
|
|
int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0);
|
|
|
|
if(ret == 0 && buf[0] != '\0') {
|
|
|
|
// again, remove executable name with dirname()
|
|
|
|
// on FreeBSD dirname() seems to use some internal buffer
|
|
|
|
dir = strdup(dirname(buf));
|
|
|
|
}
|
|
|
|
#elif defined __linux || defined EDUKE32_BSD
|
2014-12-08 04:31:57 +00:00
|
|
|
char buf[PATH_MAX] = {0};
|
|
|
|
char buf2[PATH_MAX] = {0};
|
|
|
|
# ifdef __linux
|
2015-01-11 04:53:30 +00:00
|
|
|
Bsnprintf(buf, sizeof(buf), "/proc/%d/exe", getpid());
|
2014-12-08 04:31:57 +00:00
|
|
|
# else // the BSDs.. except for FreeBSD which has a sysctl
|
2015-01-11 04:53:30 +00:00
|
|
|
Bsnprintf(buf, sizeof(buf), "/proc/%d/file", getpid());
|
2014-12-08 04:31:57 +00:00
|
|
|
# endif
|
|
|
|
int len = readlink(buf, buf2, sizeof(buf2));
|
|
|
|
if (len != -1) {
|
|
|
|
// remove executable name with dirname(3)
|
|
|
|
// on Linux, dirname() will modify buf2 (cutting off executable name) and return it
|
|
|
|
// on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup()
|
2015-01-11 04:53:30 +00:00
|
|
|
dir = Bstrdup(dirname(buf2));
|
2014-12-08 04:31:57 +00:00
|
|
|
}
|
2006-07-01 01:40:18 +00:00
|
|
|
#endif
|
2014-12-08 07:32:58 +00:00
|
|
|
|
2014-12-08 04:31:57 +00:00
|
|
|
return dir;
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bcorrectfilename(char *filename, int32_t removefn)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
char *fn;
|
2008-06-11 02:33:23 +00:00
|
|
|
char *tokarr[64], *first, *next = NULL, *token;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i, ntok = 0, leadslash = 0, trailslash = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2009-10-07 06:47:35 +00:00
|
|
|
fn = Bstrdup(filename);
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!fn) return -1;
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
for (first=fn; *first; first++)
|
|
|
|
{
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2006-04-24 19:04:22 +00:00
|
|
|
if (*first == '\\') *first = '/';
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
leadslash = (*fn == '/');
|
|
|
|
trailslash = (first>fn && first[-1] == '/');
|
|
|
|
|
|
|
|
first = fn;
|
2007-12-12 17:42:14 +00:00
|
|
|
do
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
token = Bstrtoken(first, "/", &next, 1);
|
|
|
|
first = NULL;
|
|
|
|
if (!token) break;
|
|
|
|
else if (token[0] == 0) continue;
|
|
|
|
else if (token[0] == '.' && token[1] == 0) continue;
|
|
|
|
else if (token[0] == '.' && token[1] == '.' && token[2] == 0) ntok = max(0,ntok-1);
|
|
|
|
else tokarr[ntok++] = token;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (1);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (!trailslash && removefn) { ntok = max(0,ntok-1); trailslash = 1; }
|
2006-04-24 19:04:22 +00:00
|
|
|
if (ntok == 0 && trailslash && leadslash) trailslash = 0;
|
|
|
|
|
|
|
|
first = filename;
|
|
|
|
if (leadslash) *(first++) = '/';
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=0; i<ntok; i++)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (i>0) *(first++) = '/';
|
|
|
|
for (token=tokarr[i]; *token; token++)
|
|
|
|
*(first++) = *token;
|
|
|
|
}
|
|
|
|
if (trailslash) *(first++) = '/';
|
|
|
|
*(first++) = 0;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2006-04-24 18:52:29 +00:00
|
|
|
Bfree(fn);
|
2006-04-24 19:04:22 +00:00
|
|
|
return 0;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bcanonicalisefilename(char *filename, int32_t removefn)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
char cwd[BMAX_PATH];
|
2006-04-24 19:04:22 +00:00
|
|
|
char *fnp = filename;
|
|
|
|
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2015-01-11 04:53:30 +00:00
|
|
|
int drv = 0;
|
|
|
|
|
|
|
|
if (filename[0] && filename[1] == ':')
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
// filename is prefixed with a drive
|
|
|
|
drv = toupper(filename[0]) - 'A' + 1;
|
|
|
|
fnp += 2;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-01-11 04:53:30 +00:00
|
|
|
|
|
|
|
if (!_getdcwd(drv, cwd, sizeof(cwd)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (char *p = cwd; *p; p++)
|
|
|
|
if (*p == '\\')
|
|
|
|
*p = '/';
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
if (!getcwd(cwd, sizeof(cwd)))
|
|
|
|
return -1;
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *p = Bstrrchr(cwd, '/');
|
|
|
|
if (!p || p[1])
|
|
|
|
Bstrcat(cwd, "/");
|
|
|
|
|
|
|
|
char fn[BMAX_PATH];
|
|
|
|
Bstrcpy(fn, fnp);
|
|
|
|
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2015-01-11 04:53:30 +00:00
|
|
|
for (p = fn; *p; p++)
|
|
|
|
if (*p == '\\')
|
|
|
|
*p = '/';
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (fn[0] != '/')
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
// we are dealing with a path relative to the current directory
|
2015-01-11 04:53:30 +00:00
|
|
|
Bstrcpy(filename, cwd);
|
|
|
|
Bstrcat(filename, fn);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2006-04-24 19:04:22 +00:00
|
|
|
filename[0] = cwd[0];
|
|
|
|
filename[1] = ':';
|
|
|
|
filename[2] = 0;
|
2015-01-11 04:53:30 +00:00
|
|
|
Bstrcat(filename, fn);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
Bstrcpy(filename, fn);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
fnp = filename;
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _WIN32
|
2015-01-11 04:53:30 +00:00
|
|
|
fnp += 2; // skip the drive
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2015-01-11 04:53:30 +00:00
|
|
|
UNREFERENCED_PARAMETER(removefn); // change the call below to use removefn instead of 1?
|
|
|
|
return Bcorrectfilename(fnp, 1);
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *Bgetsystemdrives(void)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2006-04-24 19:04:22 +00:00
|
|
|
char *str, *p;
|
|
|
|
DWORD drv, mask;
|
2015-01-11 04:53:30 +00:00
|
|
|
int32_t number = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
drv = GetLogicalDrives();
|
2015-01-11 04:53:30 +00:00
|
|
|
if (drv == 0)
|
|
|
|
return NULL;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
for (mask = 1; mask < 0x8000000l; mask <<= 1)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if ((drv & mask) == 0)
|
|
|
|
continue;
|
2006-04-24 19:04:22 +00:00
|
|
|
number++;
|
|
|
|
}
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
str = p = (char *)Bmalloc(1 + (3 * number));
|
|
|
|
if (!str)
|
|
|
|
return NULL;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
number = 0;
|
2015-01-11 04:53:30 +00:00
|
|
|
for (mask = 1; mask < 0x8000000l; mask <<= 1, number++)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if ((drv & mask) == 0)
|
|
|
|
continue;
|
2006-04-24 19:04:22 +00:00
|
|
|
*(p++) = 'A' + number;
|
|
|
|
*(p++) = ':';
|
|
|
|
*(p++) = 0;
|
|
|
|
}
|
|
|
|
*(p++) = 0;
|
|
|
|
|
|
|
|
return str;
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
// Perhaps have Unix OS's put /, /home/user, and /mnt/* in the "drives" list?
|
|
|
|
return NULL;
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bfilelength(int32_t fd)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2012-11-15 14:27:57 +00:00
|
|
|
struct Bstat st;
|
2015-01-11 04:53:30 +00:00
|
|
|
return (Bfstat(fd, &st) < 0) ? -1 : (int32_t)(st.st_size);
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2014-02-11 07:17:45 +00:00
|
|
|
intptr_t dir;
|
2006-04-24 19:04:22 +00:00
|
|
|
struct _finddata_t fid;
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
DIR *dir;
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
struct Bdirent info;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t status;
|
2006-04-24 19:04:22 +00:00
|
|
|
char name[1];
|
2006-04-23 06:44:19 +00:00
|
|
|
} BDIR_real;
|
|
|
|
|
2011-01-16 02:50:27 +00:00
|
|
|
BDIR *Bopendir(const char *name)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
BDIR_real *dirr;
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
char *t, *tt;
|
|
|
|
t = (char *)Bmalloc(Bstrlen(name) + 1 + 4);
|
|
|
|
if (!t)
|
|
|
|
return NULL;
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
dirr = (BDIR_real *)Bmalloc(sizeof(BDIR_real) + Bstrlen(name));
|
2007-12-12 17:42:14 +00:00
|
|
|
if (!dirr)
|
|
|
|
{
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(t);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
2015-01-11 04:53:30 +00:00
|
|
|
Bstrcpy(t, name);
|
|
|
|
tt = t + Bstrlen(name) - 1;
|
|
|
|
while (*tt == ' ' && tt > t) tt--;
|
|
|
|
if (*tt != '/' && *tt != '\\')
|
|
|
|
*(++tt) = '/';
|
2006-04-24 19:04:22 +00:00
|
|
|
*(++tt) = '*';
|
|
|
|
*(++tt) = '.';
|
|
|
|
*(++tt) = '*';
|
|
|
|
*(++tt) = 0;
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
dirr->dir = _findfirst(t, &dirr->fid);
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(t);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (dirr->dir == -1)
|
|
|
|
{
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(dirr);
|
2006-04-24 19:04:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->dir = opendir(name);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (dirr->dir == NULL)
|
|
|
|
{
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(dirr);
|
2006-04-24 19:04:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->status = 0;
|
2015-01-11 04:53:30 +00:00
|
|
|
Bstrcpy(dirr->name, name);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-01-16 02:50:27 +00:00
|
|
|
return (BDIR *)dirr;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
struct Bdirent *Breaddir(BDIR *dir)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2011-01-16 02:50:27 +00:00
|
|
|
BDIR_real *dirr = (BDIR_real *)dir;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
2007-12-12 17:42:14 +00:00
|
|
|
if (dirr->status > 0)
|
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if (_findnext(dirr->dir, &dirr->fid) != 0)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->status = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2015-01-11 04:53:30 +00:00
|
|
|
dirr->info.namlen = Bstrlen(dirr->fid.name);
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->info.name = dirr->fid.name;
|
|
|
|
dirr->status++;
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2015-01-11 04:53:30 +00:00
|
|
|
struct dirent *de = readdir(dirr->dir);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (de == NULL)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->status = -1;
|
|
|
|
return NULL;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->status++;
|
|
|
|
}
|
2015-01-11 04:53:30 +00:00
|
|
|
dirr->info.namlen = Bstrlen(de->d_name);
|
|
|
|
dirr->info.name = de->d_name;
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->info.mode = 0;
|
|
|
|
dirr->info.size = 0;
|
|
|
|
dirr->info.mtime = 0;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *fn = (char *)Bmalloc(Bstrlen(dirr->name) + 1 + dirr->info.namlen + 1);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (fn)
|
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
Bsprintf(fn, "%s/%s", dirr->name, dirr->info.name);
|
|
|
|
struct Bstat st;
|
2010-05-25 10:56:00 +00:00
|
|
|
if (!Bstat(fn, &st))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
dirr->info.mode = st.st_mode;
|
|
|
|
dirr->info.size = st.st_size;
|
|
|
|
dirr->info.mtime = st.st_mtime;
|
|
|
|
}
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(fn);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
return &dirr->info;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t Bclosedir(BDIR *dir)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2011-01-16 02:50:27 +00:00
|
|
|
BDIR_real *dirr = (BDIR_real *)dir;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-04-23 06:44:19 +00:00
|
|
|
#ifdef _MSC_VER
|
2006-04-24 19:04:22 +00:00
|
|
|
_findclose(dirr->dir);
|
2006-04-23 06:44:19 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
closedir(dirr->dir);
|
2006-04-23 06:44:19 +00:00
|
|
|
#endif
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(dirr);
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
return 0;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop)
|
2006-04-23 06:44:19 +00:00
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if (!ptrptr)
|
|
|
|
return NULL;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
char *p = s ? s : *ptrptr;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
if (!p)
|
|
|
|
return NULL;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
while (*p != 0 && Bstrchr(delim, *p)) p++;
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (*p == 0)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
*ptrptr = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-01-11 04:53:30 +00:00
|
|
|
|
|
|
|
char * const start = p;
|
|
|
|
|
|
|
|
while (*p != 0 && !Bstrchr(delim, *p)) p++;
|
|
|
|
|
|
|
|
if (*p == 0)
|
|
|
|
*ptrptr = NULL;
|
2007-12-12 17:42:14 +00:00
|
|
|
else
|
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if (chop)
|
|
|
|
*(p++) = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
*ptrptr = p;
|
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
return start;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
2012-03-12 04:48:42 +00:00
|
|
|
char *Bstrtolower(char *str)
|
|
|
|
{
|
2015-01-11 04:53:30 +00:00
|
|
|
if (!str)
|
|
|
|
return NULL;
|
2012-03-12 04:48:42 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
int len = Bstrlen(str);
|
2012-03-12 04:48:42 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
if (len <= 0)
|
|
|
|
return str;
|
2012-03-12 04:48:42 +00:00
|
|
|
|
2015-01-11 04:53:30 +00:00
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
*(str + i) = Btolower(*(str + i));
|
|
|
|
i++;
|
|
|
|
} while (--len);
|
2012-03-12 04:48:42 +00:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Brute-force case-insensitive, slash-insensitive, * and ? wildcard matcher
|
|
|
|
//Returns: 1:matches, 0:doesn't match
|
2014-10-25 03:29:21 +00:00
|
|
|
#ifndef WITHKPLIB
|
|
|
|
extern char toupperlookup[256];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
static int32_t wildmatch(const char *match, const char *wild)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
do
|
|
|
|
{
|
2014-10-25 03:29:21 +00:00
|
|
|
if (*match && (toupperlookup[*wild] == toupperlookup[*match] || *wild == '?'))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2014-10-25 03:29:21 +00:00
|
|
|
wild++, match++;
|
2006-04-24 19:04:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-10-25 03:29:21 +00:00
|
|
|
else if ((*match|*wild) == '\0')
|
|
|
|
return 1;
|
|
|
|
else if (*wild == '*')
|
|
|
|
{
|
2015-01-15 06:45:27 +00:00
|
|
|
do { wild++; } while (*wild == '*');
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (*wild == '\0')
|
|
|
|
return 1;
|
|
|
|
while (*match && toupperlookup[*match] != toupperlookup[*wild]) match++;
|
|
|
|
if (*match && *(match+1) && toupperlookup[*(match+1)] != toupperlookup[*(wild+1)])
|
|
|
|
{
|
|
|
|
match++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while (1);
|
2014-10-25 03:29:21 +00:00
|
|
|
if (toupperlookup[*match] == toupperlookup[*wild])
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return 0;
|
2015-01-15 06:45:27 +00:00
|
|
|
}
|
|
|
|
while (1);
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
2014-10-25 03:29:21 +00:00
|
|
|
#endif
|
2006-04-23 06:44:19 +00:00
|
|
|
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
char *Bstrlwr(char *s)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!s) return s;
|
2015-01-11 04:53:30 +00:00
|
|
|
char *t = s;
|
2007-12-12 17:42:14 +00:00
|
|
|
while (*t) { *t = Btolower(*t); t++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
return s;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *Bstrupr(char *s)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!s) return s;
|
2015-01-11 04:53:30 +00:00
|
|
|
char *t = s;
|
2007-12-12 17:42:14 +00:00
|
|
|
while (*t) { *t = Btoupper(*t); t++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
return s;
|
2006-04-23 06:44:19 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2010-01-16 20:17:33 +00:00
|
|
|
// Bgetsysmemsize() -- gets the amount of system memory in the machine
|
2006-04-23 06:44:19 +00:00
|
|
|
//
|
2012-11-05 02:49:08 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
typedef BOOL (WINAPI *aGlobalMemoryStatusExType)(LPMEMORYSTATUSEX);
|
|
|
|
#endif
|
|
|
|
|
2011-01-16 02:50:27 +00:00
|
|
|
uint32_t Bgetsysmemsize(void)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2012-09-02 14:06:30 +00:00
|
|
|
uint32_t siz = UINT32_MAX;
|
2011-01-16 02:50:27 +00:00
|
|
|
HMODULE lib = LoadLibrary("KERNEL32.DLL");
|
|
|
|
|
|
|
|
if (lib)
|
|
|
|
{
|
2012-11-05 02:49:08 +00:00
|
|
|
aGlobalMemoryStatusExType aGlobalMemoryStatusEx =
|
|
|
|
(aGlobalMemoryStatusExType)GetProcAddress(lib, "GlobalMemoryStatusEx");
|
2011-01-16 02:50:27 +00:00
|
|
|
|
|
|
|
if (aGlobalMemoryStatusEx)
|
|
|
|
{
|
|
|
|
//WinNT
|
|
|
|
MEMORYSTATUSEX memst;
|
|
|
|
memst.dwLength = sizeof(MEMORYSTATUSEX);
|
|
|
|
if (aGlobalMemoryStatusEx(&memst))
|
2012-09-02 14:06:30 +00:00
|
|
|
siz = (uint32_t)min(UINT32_MAX, memst.ullTotalPhys);
|
2011-01-16 02:50:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Yeah, there's enough Win9x hatred here that a perfectly good workaround
|
|
|
|
// has been replaced by an error message. Oh well, we don't support 9x anyway.
|
2012-03-12 04:48:42 +00:00
|
|
|
initprintf("Bgetsysmemsize(): error determining system memory size!\n");
|
2011-01-16 02:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeLibrary(lib);
|
|
|
|
}
|
|
|
|
|
|
|
|
return siz;
|
2012-05-01 12:40:08 +00:00
|
|
|
#elif (defined(_SC_PAGE_SIZE) || defined(_SC_PAGESIZE)) && defined(_SC_PHYS_PAGES) && !defined(GEKKO)
|
2012-09-02 14:06:30 +00:00
|
|
|
uint32_t siz = UINT32_MAX;
|
2011-01-16 02:50:27 +00:00
|
|
|
int64_t scpagesiz, scphyspages;
|
|
|
|
|
|
|
|
#ifdef _SC_PAGE_SIZE
|
|
|
|
scpagesiz = sysconf(_SC_PAGE_SIZE);
|
|
|
|
#else
|
|
|
|
scpagesiz = sysconf(_SC_PAGESIZE);
|
|
|
|
#endif
|
|
|
|
scphyspages = sysconf(_SC_PHYS_PAGES);
|
|
|
|
if (scpagesiz >= 0 && scphyspages >= 0)
|
2012-09-02 14:06:30 +00:00
|
|
|
siz = (uint32_t)min(UINT32_MAX, (int64_t)scpagesiz * (int64_t)scphyspages);
|
2011-01-16 02:50:27 +00:00
|
|
|
|
|
|
|
//initprintf("Bgetsysmemsize(): %d pages of %d bytes, %d bytes of system memory\n",
|
|
|
|
// scphyspages, scpagesiz, siz);
|
|
|
|
|
|
|
|
return siz;
|
|
|
|
#else
|
2012-09-02 14:06:30 +00:00
|
|
|
return UINT32_MAX;
|
2011-01-16 02:50:27 +00:00
|
|
|
#endif
|
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2012-05-01 12:40:08 +00:00
|
|
|
#ifdef GEKKO
|
|
|
|
int access(const char *pathname, int mode)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
if (stat(pathname, &st)==-1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// TODO: Check mode against st_mode
|
2013-02-18 08:50:08 +00:00
|
|
|
UNREFERENCED_PARAMETER(mode);
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2012-05-01 12:40:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
#define LIBDIVIDE_BODY
|
|
|
|
#include "libdivide.h"
|
|
|
|
|