Subversion Repositories eduke32

Rev

Rev 5005 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5005 Rev 5037
1
/*
1
/*
2
 * Playing-field leveller for Build
2
 * Playing-field leveller for Build
3
 * by Jonathon Fowler
3
 * by Jonathon Fowler
4
 *
4
 *
5
 * A note about this:
5
 * A note about this:
6
 * 1. There is some kind of problem somewhere in the functions below because
6
 * 1. There is some kind of problem somewhere in the functions below because
7
 *    compiling with __compat_h_macrodef__ disabled makes stupid things happen.
7
 *    compiling with __compat_h_macrodef__ disabled makes stupid things happen.
8
 * 2. The functions below, aside from the ones which aren't trivial, were never
8
 * 2. The functions below, aside from the ones which aren't trivial, were never
9
 *    really intended to be used for anything except tracking anr removing ties
9
 *    really intended to be used for anything except tracking anr removing ties
10
 *    to the standard C library from games. Using the Bxx versions of functions
10
 *    to the standard C library from games. Using the Bxx versions of functions
11
 *    means we can redefine those names to link up with different runtime library
11
 *    means we can redefine those names to link up with different runtime library
12
 *    names.
12
 *    names.
13
 */
13
 */
14
14
15
#include "compat.h"
15
#include "compat.h"
16
16
17
#ifdef _WIN32
17
#ifdef _WIN32
18
# include <shlobj.h>
18
# include <shlobj.h>
19
# include <direct.h>
19
# include <direct.h>
20
#elif __APPLE__
20
#elif __APPLE__
21
# include "osxbits.h"
21
# include "osxbits.h"
22
#endif
22
#endif
23
23
24
#if defined(_MSC_VER)
24
#if defined(_MSC_VER)
25
# include <io.h>
25
# include <io.h>
26
#else
26
#else
27
# include <dirent.h>
27
# include <dirent.h>
28
#endif
28
#endif
29
29
30
#if defined(__linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
30
#if defined __linux || defined EDUKE32_BSD
31
# include <libgen.h> // for dirname()
31
# include <libgen.h> // for dirname()
32
#endif
32
#endif
33
#if defined(__FreeBSD__)
33
#if defined __FreeBSD__
-
 
34
# include <limits.h> // for PATH_MAX
34
# include <sys/sysctl.h> // for sysctl() to get path to executable
35
# include <sys/sysctl.h> // for sysctl() to get path to executable
35
#endif
36
#endif
36
37
37
#include "baselayer.h"
38
#include "baselayer.h"
38
39
39
////////// PANICKING ALLOCATION FUNCTIONS //////////
40
////////// PANICKING ALLOCATION FUNCTIONS //////////
40
41
41
static void (*g_MemErrHandler)(int32_t line, const char *file, const char *func);
42
static void (*g_MemErrHandler)(int32_t line, const char *file, const char *func);
42
43
43
#ifdef DEBUGGINGAIDS
44
#ifdef DEBUGGINGAIDS
44
static const char *g_MemErrFunc = "???";
45
static const char *g_MemErrFunc = "???";
45
static const char *g_MemErrFile = "???";
46
static const char *g_MemErrFile = "???";
46
static int32_t g_MemErrLine;
47
static int32_t g_MemErrLine;
47
48
48
void xalloc_set_location(int32_t line, const char *file, const char *func)
49
void xalloc_set_location(int32_t line, const char *file, const char *func)
49
{
50
{
50
    g_MemErrLine = line;
51
    g_MemErrLine = line;
51
    g_MemErrFile = file;
52
    g_MemErrFile = file;
52
53
53
    if (func)
54
    if (func)
54
        g_MemErrFunc = func;
55
        g_MemErrFunc = func;
55
}
56
}
56
#endif
57
#endif
57
58
58
void handle_memerr(void)
59
void handle_memerr(void)
59
{
60
{
60
    if (g_MemErrHandler)
61
    if (g_MemErrHandler)
61
    {
62
    {
62
#ifdef DEBUGGINGAIDS
63
#ifdef DEBUGGINGAIDS
63
        g_MemErrHandler(g_MemErrLine, g_MemErrFile, g_MemErrFunc);
64
        g_MemErrHandler(g_MemErrLine, g_MemErrFile, g_MemErrFunc);
64
#else
65
#else
65
        g_MemErrHandler(0, "???", "???");
66
        g_MemErrHandler(0, "???", "???");
66
#endif
67
#endif
67
    }
68
    }
68
69
69
    Bexit(EXIT_FAILURE);
70
    Bexit(EXIT_FAILURE);
70
}
71
}
71
72
72
void set_memerr_handler(void(*handlerfunc)(int32_t, const char *, const char *))
73
void set_memerr_handler(void(*handlerfunc)(int32_t, const char *, const char *))
73
{
74
{
74
    g_MemErrHandler = handlerfunc;
75
    g_MemErrHandler = handlerfunc;
75
}
76
}
76
77
77
//////////
78
//////////
78
79
79
#ifndef compat_h_macrodef__
80
#ifndef compat_h_macrodef__
80
81
81
void Bassert(int expr) { assert(expr); }
82
void Bassert(int expr) { assert(expr); }
82
int32_t Brand(void) { return rand(); }
83
int32_t Brand(void) { return rand(); }
83
void *Bmalloc(bsize_t size) { return malloc(size); }
84
void *Bmalloc(bsize_t size) { return malloc(size); }
84
void Bfree(void *ptr) { Bfree(ptr); }
85
void Bfree(void *ptr) { Bfree(ptr); }
85
86
86
int32_t Bopen(const char *pathname, int32_t flags, uint32_t mode)
87
int32_t Bopen(const char *pathname, int32_t flags, uint32_t mode)
87
{
88
{
88
    int32_t n = 0, o = 0;
89
    int32_t n = 0, o = 0;
89
90
90
    if (flags & BO_BINARY)
91
    if (flags & BO_BINARY)
91
        n |= O_BINARY;
92
        n |= O_BINARY;
92
    else
93
    else
93
        n |= O_TEXT;
94
        n |= O_TEXT;
94
    if ((flags & BO_RDWR) == BO_RDWR)
95
    if ((flags & BO_RDWR) == BO_RDWR)
95
        n |= O_RDWR;
96
        n |= O_RDWR;
96
    else if ((flags & BO_RDWR) == BO_WRONLY)
97
    else if ((flags & BO_RDWR) == BO_WRONLY)
97
        n |= O_WRONLY;
98
        n |= O_WRONLY;
98
    else if ((flags & BO_RDWR) == BO_RDONLY)
99
    else if ((flags & BO_RDWR) == BO_RDONLY)
99
        n |= O_RDONLY;
100
        n |= O_RDONLY;
100
    if (flags & BO_APPEND)
101
    if (flags & BO_APPEND)
101
        n |= O_APPEND;
102
        n |= O_APPEND;
102
    if (flags & BO_CREAT)
103
    if (flags & BO_CREAT)
103
        n |= O_CREAT;
104
        n |= O_CREAT;
104
    if (flags & BO_TRUNC)
105
    if (flags & BO_TRUNC)
105
        n |= O_TRUNC;
106
        n |= O_TRUNC;
106
    if (mode & BS_IREAD)
107
    if (mode & BS_IREAD)
107
        o |= S_IREAD;
108
        o |= S_IREAD;
108
    if (mode & BS_IWRITE)
109
    if (mode & BS_IWRITE)
109
        o |= S_IWRITE;
110
        o |= S_IWRITE;
110
    if (mode & BS_IEXEC)
111
    if (mode & BS_IEXEC)
111
        o |= S_IEXEC;
112
        o |= S_IEXEC;
112
113
113
    return open(pathname, n, o);
114
    return open(pathname, n, o);
114
}
115
}
115
116
116
int32_t Bclose(int32_t fd) { return close(fd); }
117
int32_t Bclose(int32_t fd) { return close(fd); }
117
bssize_t Bwrite(int32_t fd, const void *buf, bsize_t count) { return write(fd, buf, count); }
118
bssize_t Bwrite(int32_t fd, const void *buf, bsize_t count) { return write(fd, buf, count); }
118
bssize_t Bread(int32_t fd, void *buf, bsize_t count) { return read(fd, buf, count); }
119
bssize_t Bread(int32_t fd, void *buf, bsize_t count) { return read(fd, buf, count); }
119
120
120
int32_t Blseek(int32_t fildes, int32_t offset, int32_t whence)
121
int32_t Blseek(int32_t fildes, int32_t offset, int32_t whence)
121
{
122
{
122
    switch (whence)
123
    switch (whence)
123
    {
124
    {
124
        case BSEEK_SET: whence = SEEK_SET; break;
125
        case BSEEK_SET: whence = SEEK_SET; break;
125
        case BSEEK_CUR: whence = SEEK_CUR; break;
126
        case BSEEK_CUR: whence = SEEK_CUR; break;
126
        case BSEEK_END: whence = SEEK_END; break;
127
        case BSEEK_END: whence = SEEK_END; break;
127
    }
128
    }
128
    return lseek(fildes, offset, whence);
129
    return lseek(fildes, offset, whence);
129
}
130
}
130
131
131
BFILE *Bfopen(const char *path, const char *mode) { return (BFILE *)fopen(path, mode); }
132
BFILE *Bfopen(const char *path, const char *mode) { return (BFILE *)fopen(path, mode); }
132
int32_t Bfclose(BFILE *stream) { return fclose((FILE *)stream); }
133
int32_t Bfclose(BFILE *stream) { return fclose((FILE *)stream); }
133
void Brewind(BFILE *stream) { rewind((FILE *)stream); }
134
void Brewind(BFILE *stream) { rewind((FILE *)stream); }
134
int32_t Bfgetc(BFILE *stream) { return fgetc((FILE *)stream); }
135
int32_t Bfgetc(BFILE *stream) { return fgetc((FILE *)stream); }
135
char *Bfgets(char *s, int32_t size, BFILE *stream) { return fgets(s, size, (FILE *)stream); }
136
char *Bfgets(char *s, int32_t size, BFILE *stream) { return fgets(s, size, (FILE *)stream); }
136
int32_t Bfputc(int32_t c, BFILE *stream) { return fputc(c, (FILE *)stream); }
137
int32_t Bfputc(int32_t c, BFILE *stream) { return fputc(c, (FILE *)stream); }
137
int32_t Bfputs(const char *s, BFILE *stream) { return fputs(s, (FILE *)stream); }
138
int32_t Bfputs(const char *s, BFILE *stream) { return fputs(s, (FILE *)stream); }
138
bsize_t Bfread(void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fread(ptr, size, nmemb, (FILE *)stream); }
139
bsize_t Bfread(void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fread(ptr, size, nmemb, (FILE *)stream); }
139
bsize_t Bfwrite(const void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fwrite(ptr, size, nmemb, (FILE *)stream); }
140
bsize_t Bfwrite(const void *ptr, bsize_t size, bsize_t nmemb, BFILE *stream) { return fwrite(ptr, size, nmemb, (FILE *)stream); }
140
char *Bstrdup(const char *s) { return strdup(s); }
141
char *Bstrdup(const char *s) { return strdup(s); }
141
char *Bstrcpy(char *dest, const char *src) { return strcpy(dest, src); }
142
char *Bstrcpy(char *dest, const char *src) { return strcpy(dest, src); }
142
char *Bstrncpy(char *dest, const char *src, bsize_t n) { return Bstrncpy(dest, src, n); }
143
char *Bstrncpy(char *dest, const char *src, bsize_t n) { return Bstrncpy(dest, src, n); }
143
int32_t Bstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); }
144
int32_t Bstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); }
144
int32_t Bstrncmp(const char *s1, const char *s2, bsize_t n) { return strncmp(s1, s2, n); }
145
int32_t Bstrncmp(const char *s1, const char *s2, bsize_t n) { return strncmp(s1, s2, n); }
145
146
146
int32_t Bstrcasecmp(const char *s1, const char *s2)
147
int32_t Bstrcasecmp(const char *s1, const char *s2)
147
{
148
{
148
#ifdef _MSC_VER
149
#ifdef _MSC_VER
149
    return _stricmp(s1, s2);
150
    return _stricmp(s1, s2);
150
#else
151
#else
151
    return strcasecmp(s1, s2);
152
    return strcasecmp(s1, s2);
152
#endif
153
#endif
153
}
154
}
154
155
155
int32_t Bstrncasecmp(const char *s1, const char *s2, bsize_t n)
156
int32_t Bstrncasecmp(const char *s1, const char *s2, bsize_t n)
156
{
157
{
157
#ifdef _MSC_VER
158
#ifdef _MSC_VER
158
    return _strnicmp(s1, s2, n);
159
    return _strnicmp(s1, s2, n);
159
#else
160
#else
160
    return strncasecmp(s1, s2, n);
161
    return strncasecmp(s1, s2, n);
161
#endif
162
#endif
162
}
163
}
163
164
164
char *Bstrcat(char *dest, const char *src) { return strcat(dest, src); }
165
char *Bstrcat(char *dest, const char *src) { return strcat(dest, src); }
165
char *Bstrncat(char *dest, const char *src, bsize_t n) { return strncat(dest, src, n); }
166
char *Bstrncat(char *dest, const char *src, bsize_t n) { return strncat(dest, src, n); }
166
bsize_t Bstrlen(const char *s) { return strlen(s); }
167
bsize_t Bstrlen(const char *s) { return strlen(s); }
167
char *Bstrchr(const char *s, int32_t c) { return strchr(s, c); }
168
char *Bstrchr(const char *s, int32_t c) { return strchr(s, c); }
168
char *Bstrrchr(const char *s, int32_t c) { return strrchr(s, c); }
169
char *Bstrrchr(const char *s, int32_t c) { return strrchr(s, c); }
169
int32_t Batoi(const char *nptr) { return strtol(nptr, NULL, 10); }
170
int32_t Batoi(const char *nptr) { return strtol(nptr, NULL, 10); }
170
int32_t Batol(const char *nptr) { return strtol(nptr, NULL, 10); }
171
int32_t Batol(const char *nptr) { return strtol(nptr, NULL, 10); }
171
int32_t Bstrtol(const char *nptr, char **endptr, int32_t base) { return strtol(nptr, endptr, base); }
172
int32_t Bstrtol(const char *nptr, char **endptr, int32_t base) { return strtol(nptr, endptr, base); }
172
uint32_t Bstrtoul(const char *nptr, char **endptr, int32_t base) { return strtoul(nptr, endptr, base); }
173
uint32_t Bstrtoul(const char *nptr, char **endptr, int32_t base) { return strtoul(nptr, endptr, base); }
173
void *Bmemcpy(void *dest, const void *src, bsize_t n) { return memcpy(dest, src, n); }
174
void *Bmemcpy(void *dest, const void *src, bsize_t n) { return memcpy(dest, src, n); }
174
void *Bmemmove(void *dest, const void *src, bsize_t n) { return memmove(dest, src, n); }
175
void *Bmemmove(void *dest, const void *src, bsize_t n) { return memmove(dest, src, n); }
175
void *Bmemchr(const void *s, int32_t c, bsize_t n) { return memchr(s, c, n); }
176
void *Bmemchr(const void *s, int32_t c, bsize_t n) { return memchr(s, c, n); }
176
void *Bmemset(void *s, int32_t c, bsize_t n) { return memset(s, c, n); }
177
void *Bmemset(void *s, int32_t c, bsize_t n) { return memset(s, c, n); }
177
178
178
int32_t Bprintf(const char *format, ...)
179
int32_t Bprintf(const char *format, ...)
179
{
180
{
180
    va_list ap;
181
    va_list ap;
181
    int32_t r;
182
    int32_t r;
182
183
183
    va_start(ap, format);
184
    va_start(ap, format);
184
#ifdef _MSC_VER
185
#ifdef _MSC_VER
185
    r = _vprintf(format, ap);
186
    r = _vprintf(format, ap);
186
#else
187
#else
187
    r = vprintf(format, ap);
188
    r = vprintf(format, ap);
188
#endif
189
#endif
189
    va_end(ap);
190
    va_end(ap);
190
    return r;
191
    return r;
191
}
192
}
192
193
193
int32_t Bsprintf(char *str, const char *format, ...)
194
int32_t Bsprintf(char *str, const char *format, ...)
194
{
195
{
195
    va_list ap;
196
    va_list ap;
196
    int32_t r;
197
    int32_t r;
197
198
198
    va_start(ap, format);
199
    va_start(ap, format);
199
#ifdef _MSC_VER
200
#ifdef _MSC_VER
200
    r = _vsprintf(str, format, ap);
201
    r = _vsprintf(str, format, ap);
201
#else
202
#else
202
    r = vsprintf(str, format, ap);
203
    r = vsprintf(str, format, ap);
203
#endif
204
#endif
204
    va_end(ap);
205
    va_end(ap);
205
    return r;
206
    return r;
206
}
207
}
207
208
208
int32_t Bsnprintf(char *str, bsize_t size, const char *format, ...)
209
int32_t Bsnprintf(char *str, bsize_t size, const char *format, ...)
209
{
210
{
210
    va_list ap;
211
    va_list ap;
211
    int32_t r;
212
    int32_t r;
212
213
213
    va_start(ap, format);
214
    va_start(ap, format);
214
#ifdef _MSC_VER
215
#ifdef _MSC_VER
215
    r = _vsnprintf(str, size, format, ap);
216
    r = _vsnprintf(str, size, format, ap);
216
#else
217
#else
217
    r = vsnprintf(str, size, format, ap);
218
    r = vsnprintf(str, size, format, ap);
218
#endif
219
#endif
219
    va_end(ap);
220
    va_end(ap);
220
    return r;
221
    return r;
221
}
222
}
222
223
223
int32_t Bvsnprintf(char *str, bsize_t size, const char *format, va_list ap)
224
int32_t Bvsnprintf(char *str, bsize_t size, const char *format, va_list ap)
224
{
225
{
225
#ifdef _MSC_VER
226
#ifdef _MSC_VER
226
    return _vsnprintf(str, size, format, ap);
227
    return _vsnprintf(str, size, format, ap);
227
#else
228
#else
228
    return vsnprintf(str, size, format, ap);
229
    return vsnprintf(str, size, format, ap);
229
#endif
230
#endif
230
}
231
}
231
232
232
char *Bgetenv(const char *name) { return getenv(name); }
233
char *Bgetenv(const char *name) { return getenv(name); }
233
char *Bgetcwd(char *buf, bsize_t size) { return getcwd(buf, size); }
234
char *Bgetcwd(char *buf, bsize_t size) { return getcwd(buf, size); }
234
235
235
#endif  // __compat_h_macrodef__
236
#endif  // __compat_h_macrodef__
236
237
237
238
238
//
239
//
239
// Stuff which must be a function
240
// Stuff which must be a function
240
//
241
//
241
#ifdef _WIN32
242
#ifdef _WIN32
242
typedef BOOL (WINAPI * aSHGetSpecialFolderPathAtype)(HWND, LPTSTR, int, BOOL);
243
typedef BOOL (WINAPI * aSHGetSpecialFolderPathAtype)(HWND, LPTSTR, int, BOOL);
243
#endif
244
#endif
244
245
245
char *Bgethomedir(void)
246
char *Bgethomedir(void)
246
{
247
{
247
#ifdef _WIN32
248
#ifdef _WIN32
248
    aSHGetSpecialFolderPathAtype aSHGetSpecialFolderPathA;
249
    aSHGetSpecialFolderPathAtype aSHGetSpecialFolderPathA;
249
    TCHAR appdata[MAX_PATH];
250
    TCHAR appdata[MAX_PATH];
250
    int32_t loaded = 0;
251
    int32_t loaded = 0;
251
    HMODULE hShell32 = GetModuleHandle("shell32.dll");
252
    HMODULE hShell32 = GetModuleHandle("shell32.dll");
252
253
253
    if (hShell32 == NULL)
254
    if (hShell32 == NULL)
254
    {
255
    {
255
        hShell32 = LoadLibrary("shell32.dll");
256
        hShell32 = LoadLibrary("shell32.dll");
256
        loaded = 1;
257
        loaded = 1;
257
    }
258
    }
258
259
259
    if (hShell32 == NULL)
260
    if (hShell32 == NULL)
260
        return NULL;
261
        return NULL;
261
262
262
    aSHGetSpecialFolderPathA = (aSHGetSpecialFolderPathAtype)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
263
    aSHGetSpecialFolderPathA = (aSHGetSpecialFolderPathAtype)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
263
    if (aSHGetSpecialFolderPathA != NULL)
264
    if (aSHGetSpecialFolderPathA != NULL)
264
        if (SUCCEEDED(aSHGetSpecialFolderPathA(NULL, appdata, CSIDL_APPDATA, FALSE)))
265
        if (SUCCEEDED(aSHGetSpecialFolderPathA(NULL, appdata, CSIDL_APPDATA, FALSE)))
265
        {
266
        {
266
            if (loaded)
267
            if (loaded)
267
                FreeLibrary(hShell32);
268
                FreeLibrary(hShell32);
268
            return Bstrdup(appdata);
269
            return Bstrdup(appdata);
269
        }
270
        }
270
271
271
    if (loaded)
272
    if (loaded)
272
        FreeLibrary(hShell32);
273
        FreeLibrary(hShell32);
273
    return NULL;
274
    return NULL;
274
#elif defined EDUKE32_OSX
275
#elif defined EDUKE32_OSX
275
    return osx_gethomedir();
276
    return osx_gethomedir();
276
#elif defined(GEKKO)
277
#elif defined(GEKKO)
277
    // return current drive's name
278
    // return current drive's name
278
    char *drv, cwd[BMAX_PATH] = {0};
279
    char *drv, cwd[BMAX_PATH] = {0};
279
    getcwd(cwd, BMAX_PATH);
280
    getcwd(cwd, BMAX_PATH);
280
    drv = strchr(cwd, ':');
281
    drv = strchr(cwd, ':');
281
    if (drv)
282
    if (drv)
282
        drv[1] = '\0';
283
        drv[1] = '\0';
283
    return Bstrdup(cwd);
284
    return Bstrdup(cwd);
284
#else
285
#else
285
    char *e = getenv("HOME");
286
    char *e = getenv("HOME");
286
    if (!e) return NULL;
287
    if (!e) return NULL;
287
    return Bstrdup(e);
288
    return Bstrdup(e);
288
#endif
289
#endif
289
}
290
}
290
291
291
char *Bgetappdir(void)
292
char *Bgetappdir(void)
292
{
293
{
293
    char *dir = NULL;
294
    char *dir = NULL;
294
295
295
#ifdef _WIN32
296
#ifdef _WIN32
296
        TCHAR appdir[MAX_PATH];
297
        TCHAR appdir[MAX_PATH];
297
298
298
        if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) {
299
        if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) {
299
                // trim off the filename
300
                // trim off the filename
300
                char *slash = Bstrrchr(appdir, '\\');
301
                char *slash = Bstrrchr(appdir, '\\');
301
                if (slash) slash[0] = 0;
302
                if (slash) slash[0] = 0;
302
                dir = Bstrdup(appdir);
303
                dir = Bstrdup(appdir);
303
    }
304
    }
304
305
305
#elif defined EDUKE32_OSX
306
#elif defined EDUKE32_OSX
306
    dir = osx_getappdir();
307
    dir = osx_getappdir();
-
 
308
#elif defined __FreeBSD__
-
 
309
    // the sysctl should also work when /proc/ is not mounted (which seems to
-
 
310
    // be common on FreeBSD), so use it..
-
 
311
    char buf[PATH_MAX] = {0};
-
 
312
    int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
-
 
313
    size_t len = sizeof(buf)-1;
-
 
314
    int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0);
-
 
315
    if(ret == 0 && buf[0] != '\0') {
-
 
316
        // again, remove executable name with dirname()
-
 
317
        // on FreeBSD dirname() seems to use some internal buffer
-
 
318
        dir = strdup(dirname(buf));
-
 
319
    }
307
#elif defined(__linux) || defined(__NetBSD__) || defined(__OpenBSD__)
320
#elif defined __linux || defined EDUKE32_BSD
308
    char buf[PATH_MAX] = {0};
321
    char buf[PATH_MAX] = {0};
309
    char buf2[PATH_MAX] = {0};
322
    char buf2[PATH_MAX] = {0};
310
#  ifdef __linux
323
#  ifdef __linux
311
    Bsnprintf(buf, sizeof(buf), "/proc/%d/exe", getpid());
324
    Bsnprintf(buf, sizeof(buf), "/proc/%d/exe", getpid());
312
#  else // the BSDs.. except for FreeBSD which has a sysctl
325
#  else // the BSDs.. except for FreeBSD which has a sysctl
313
    Bsnprintf(buf, sizeof(buf), "/proc/%d/file", getpid());
326
    Bsnprintf(buf, sizeof(buf), "/proc/%d/file", getpid());
314
#  endif
327
#  endif
315
    int len = readlink(buf, buf2, sizeof(buf2));
328
    int len = readlink(buf, buf2, sizeof(buf2));
316
    if (len != -1) {
329
    if (len != -1) {
317
        // remove executable name with dirname(3)
330
        // remove executable name with dirname(3)
318
        // on Linux, dirname() will modify buf2 (cutting off executable name) and return it
331
        // on Linux, dirname() will modify buf2 (cutting off executable name) and return it
319
        // on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup()
332
        // on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup()
320
        dir = Bstrdup(dirname(buf2));
333
        dir = Bstrdup(dirname(buf2));
321
    }
334
    }
322
#elif defined(__FreeBSD__)
-
 
323
    // the sysctl should also work when /proc/ is not mounted (which seems to
-
 
324
    // be common on FreeBSD), so use it..
-
 
325
    char buf[PATH_MAX] = {0};
-
 
326
    int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
-
 
327
    size_t len = sizeof(buf)-1;
-
 
328
    int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0);
-
 
329
    if(ret == 0 && buf[0] != '\0') {
-
 
330
        // again, remove executable name with dirname()
-
 
331
        // on FreeBSD dirname() seems to use some internal buffer
-
 
332
        dir = strdup(dirname(buf));
-
 
333
    }
-
 
334
#endif
335
#endif
335
336
336
    return dir;
337
    return dir;
337
}
338
}
338
339
339
int32_t Bcorrectfilename(char *filename, int32_t removefn)
340
int32_t Bcorrectfilename(char *filename, int32_t removefn)
340
{
341
{
341
    char *fn;
342
    char *fn;
342
    char *tokarr[64], *first, *next = NULL, *token;
343
    char *tokarr[64], *first, *next = NULL, *token;
343
    int32_t i, ntok = 0, leadslash = 0, trailslash = 0;
344
    int32_t i, ntok = 0, leadslash = 0, trailslash = 0;
344
345
345
    fn = Bstrdup(filename);
346
    fn = Bstrdup(filename);
346
    if (!fn) return -1;
347
    if (!fn) return -1;
347
348
348
    for (first=fn; *first; first++)
349
    for (first=fn; *first; first++)
349
    {
350
    {
350
#ifdef _WIN32
351
#ifdef _WIN32
351
        if (*first == '\\') *first = '/';
352
        if (*first == '\\') *first = '/';
352
#endif
353
#endif
353
    }
354
    }
354
    leadslash = (*fn == '/');
355
    leadslash = (*fn == '/');
355
    trailslash = (first>fn && first[-1] == '/');
356
    trailslash = (first>fn && first[-1] == '/');
356
357
357
    first = fn;
358
    first = fn;
358
    do
359
    do
359
    {
360
    {
360
        token = Bstrtoken(first, "/", &next, 1);
361
        token = Bstrtoken(first, "/", &next, 1);
361
        first = NULL;
362
        first = NULL;
362
        if (!token) break;
363
        if (!token) break;
363
        else if (token[0] == 0) continue;
364
        else if (token[0] == 0) continue;
364
        else if (token[0] == '.' && token[1] == 0) continue;
365
        else if (token[0] == '.' && token[1] == 0) continue;
365
        else if (token[0] == '.' && token[1] == '.' && token[2] == 0) ntok = max(0,ntok-1);
366
        else if (token[0] == '.' && token[1] == '.' && token[2] == 0) ntok = max(0,ntok-1);
366
        else tokarr[ntok++] = token;
367
        else tokarr[ntok++] = token;
367
    }
368
    }
368
    while (1);
369
    while (1);
369
370
370
    if (!trailslash && removefn) { ntok = max(0,ntok-1); trailslash = 1; }
371
    if (!trailslash && removefn) { ntok = max(0,ntok-1); trailslash = 1; }
371
    if (ntok == 0 && trailslash && leadslash) trailslash = 0;
372
    if (ntok == 0 && trailslash && leadslash) trailslash = 0;
372
373
373
    first = filename;
374
    first = filename;
374
    if (leadslash) *(first++) = '/';
375
    if (leadslash) *(first++) = '/';
375
    for (i=0; i<ntok; i++)
376
    for (i=0; i<ntok; i++)
376
    {
377
    {
377
        if (i>0) *(first++) = '/';
378
        if (i>0) *(first++) = '/';
378
        for (token=tokarr[i]; *token; token++)
379
        for (token=tokarr[i]; *token; token++)
379
            *(first++) = *token;
380
            *(first++) = *token;
380
    }
381
    }
381
    if (trailslash) *(first++) = '/';
382
    if (trailslash) *(first++) = '/';
382
    *(first++) = 0;
383
    *(first++) = 0;
383
384
384
    Bfree(fn);
385
    Bfree(fn);
385
    return 0;
386
    return 0;
386
}
387
}
387
388
388
int32_t Bcanonicalisefilename(char *filename, int32_t removefn)
389
int32_t Bcanonicalisefilename(char *filename, int32_t removefn)
389
{
390
{
390
    char cwd[BMAX_PATH];
391
    char cwd[BMAX_PATH];
391
    char *fnp = filename;
392
    char *fnp = filename;
392
393
393
#ifdef _WIN32
394
#ifdef _WIN32
394
    int drv = 0;
395
    int drv = 0;
395
396
396
    if (filename[0] && filename[1] == ':')
397
    if (filename[0] && filename[1] == ':')
397
    {
398
    {
398
        // filename is prefixed with a drive
399
        // filename is prefixed with a drive
399
        drv = toupper(filename[0]) - 'A' + 1;
400
        drv = toupper(filename[0]) - 'A' + 1;
400
        fnp += 2;
401
        fnp += 2;
401
    }
402
    }
402
403
403
    if (!_getdcwd(drv, cwd, sizeof(cwd)))
404
    if (!_getdcwd(drv, cwd, sizeof(cwd)))
404
        return -1;
405
        return -1;
405
406
406
    for (char *p = cwd; *p; p++)
407
    for (char *p = cwd; *p; p++)
407
        if (*p == '\\')
408
        if (*p == '\\')
408
            *p = '/';
409
            *p = '/';
409
#else
410
#else
410
    if (!getcwd(cwd, sizeof(cwd)))
411
    if (!getcwd(cwd, sizeof(cwd)))
411
        return -1;
412
        return -1;
412
#endif
413
#endif
413
414
414
    char *p = Bstrrchr(cwd, '/');
415
    char *p = Bstrrchr(cwd, '/');
415
    if (!p || p[1])
416
    if (!p || p[1])
416
        Bstrcat(cwd, "/");
417
        Bstrcat(cwd, "/");
417
418
418
    char fn[BMAX_PATH];
419
    char fn[BMAX_PATH];
419
    Bstrcpy(fn, fnp);
420
    Bstrcpy(fn, fnp);
420
421
421
#ifdef _WIN32
422
#ifdef _WIN32
422
    for (p = fn; *p; p++)
423
    for (p = fn; *p; p++)
423
        if (*p == '\\')
424
        if (*p == '\\')
424
            *p = '/';
425
            *p = '/';
425
#endif
426
#endif
426
427
427
    if (fn[0] != '/')
428
    if (fn[0] != '/')
428
    {
429
    {
429
        // we are dealing with a path relative to the current directory
430
        // we are dealing with a path relative to the current directory
430
        Bstrcpy(filename, cwd);
431
        Bstrcpy(filename, cwd);
431
        Bstrcat(filename, fn);
432
        Bstrcat(filename, fn);
432
    }
433
    }
433
    else
434
    else
434
    {
435
    {
435
#ifdef _WIN32
436
#ifdef _WIN32
436
        filename[0] = cwd[0];
437
        filename[0] = cwd[0];
437
        filename[1] = ':';
438
        filename[1] = ':';
438
        filename[2] = 0;
439
        filename[2] = 0;
439
        Bstrcat(filename, fn);
440
        Bstrcat(filename, fn);
440
#else
441
#else
441
        Bstrcpy(filename, fn);
442
        Bstrcpy(filename, fn);
442
#endif
443
#endif
443
    }
444
    }
444
    fnp = filename;
445
    fnp = filename;
445
#ifdef _WIN32
446
#ifdef _WIN32
446
    fnp += 2;  // skip the drive
447
    fnp += 2;  // skip the drive
447
#endif
448
#endif
448
    UNREFERENCED_PARAMETER(removefn);  // change the call below to use removefn instead of 1?
449
    UNREFERENCED_PARAMETER(removefn);  // change the call below to use removefn instead of 1?
449
    return Bcorrectfilename(fnp, 1);
450
    return Bcorrectfilename(fnp, 1);
450
}
451
}
451
452
452
char *Bgetsystemdrives(void)
453
char *Bgetsystemdrives(void)
453
{
454
{
454
#ifdef _WIN32
455
#ifdef _WIN32
455
    char *str, *p;
456
    char *str, *p;
456
    DWORD drv, mask;
457
    DWORD drv, mask;
457
    int32_t number = 0;
458
    int32_t number = 0;
458
459
459
    drv = GetLogicalDrives();
460
    drv = GetLogicalDrives();
460
    if (drv == 0)
461
    if (drv == 0)
461
        return NULL;
462
        return NULL;
462
463
463
    for (mask = 1; mask < 0x8000000l; mask <<= 1)
464
    for (mask = 1; mask < 0x8000000l; mask <<= 1)
464
    {
465
    {
465
        if ((drv & mask) == 0)
466
        if ((drv & mask) == 0)
466
            continue;
467
            continue;
467
        number++;
468
        number++;
468
    }
469
    }
469
470
470
    str = p = (char *)Bmalloc(1 + (3 * number));
471
    str = p = (char *)Bmalloc(1 + (3 * number));
471
    if (!str)
472
    if (!str)
472
        return NULL;
473
        return NULL;
473
474
474
    number = 0;
475
    number = 0;
475
    for (mask = 1; mask < 0x8000000l; mask <<= 1, number++)
476
    for (mask = 1; mask < 0x8000000l; mask <<= 1, number++)
476
    {
477
    {
477
        if ((drv & mask) == 0)
478
        if ((drv & mask) == 0)
478
            continue;
479
            continue;
479
        *(p++) = 'A' + number;
480
        *(p++) = 'A' + number;
480
        *(p++) = ':';
481
        *(p++) = ':';
481
        *(p++) = 0;
482
        *(p++) = 0;
482
    }
483
    }
483
    *(p++) = 0;
484
    *(p++) = 0;
484
485
485
    return str;
486
    return str;
486
#else
487
#else
487
    // Perhaps have Unix OS's put /, /home/user, and /mnt/* in the "drives" list?
488
    // Perhaps have Unix OS's put /, /home/user, and /mnt/* in the "drives" list?
488
    return NULL;
489
    return NULL;
489
#endif
490
#endif
490
}
491
}
491
492
492
493
493
int32_t Bfilelength(int32_t fd)
494
int32_t Bfilelength(int32_t fd)
494
{
495
{
495
    struct Bstat st;
496
    struct Bstat st;
496
    return (Bfstat(fd, &st) < 0) ? -1 : (int32_t)(st.st_size);
497
    return (Bfstat(fd, &st) < 0) ? -1 : (int32_t)(st.st_size);
497
}
498
}
498
499
499
500
500
typedef struct
501
typedef struct
501
{
502
{
502
#ifdef _MSC_VER
503
#ifdef _MSC_VER
503
    intptr_t dir;
504
    intptr_t dir;
504
    struct _finddata_t fid;
505
    struct _finddata_t fid;
505
#else
506
#else
506
    DIR *dir;
507
    DIR *dir;
507
#endif
508
#endif
508
    struct Bdirent info;
509
    struct Bdirent info;
509
    int32_t status;
510
    int32_t status;
510
    char name[1];
511
    char name[1];
511
} BDIR_real;
512
} BDIR_real;
512
513
513
BDIR *Bopendir(const char *name)
514
BDIR *Bopendir(const char *name)
514
{
515
{
515
    BDIR_real *dirr;
516
    BDIR_real *dirr;
516
#ifdef _MSC_VER
517
#ifdef _MSC_VER
517
    char *t, *tt;
518
    char *t, *tt;
518
    t = (char *)Bmalloc(Bstrlen(name) + 1 + 4);
519
    t = (char *)Bmalloc(Bstrlen(name) + 1 + 4);
519
    if (!t)
520
    if (!t)
520
        return NULL;
521
        return NULL;
521
#endif
522
#endif
522
523
523
    dirr = (BDIR_real *)Bmalloc(sizeof(BDIR_real) + Bstrlen(name));
524
    dirr = (BDIR_real *)Bmalloc(sizeof(BDIR_real) + Bstrlen(name));
524
    if (!dirr)
525
    if (!dirr)
525
    {
526
    {
526
#ifdef _MSC_VER
527
#ifdef _MSC_VER
527
        Bfree(t);
528
        Bfree(t);
528
#endif
529
#endif
529
        return NULL;
530
        return NULL;
530
    }
531
    }
531
532
532
#ifdef _MSC_VER
533
#ifdef _MSC_VER
533
    Bstrcpy(t, name);
534
    Bstrcpy(t, name);
534
    tt = t + Bstrlen(name) - 1;
535
    tt = t + Bstrlen(name) - 1;
535
    while (*tt == ' ' && tt > t) tt--;
536
    while (*tt == ' ' && tt > t) tt--;
536
    if (*tt != '/' && *tt != '\\')
537
    if (*tt != '/' && *tt != '\\')
537
        *(++tt) = '/';
538
        *(++tt) = '/';
538
    *(++tt) = '*';
539
    *(++tt) = '*';
539
    *(++tt) = '.';
540
    *(++tt) = '.';
540
    *(++tt) = '*';
541
    *(++tt) = '*';
541
    *(++tt) = 0;
542
    *(++tt) = 0;
542
543
543
    dirr->dir = _findfirst(t, &dirr->fid);
544
    dirr->dir = _findfirst(t, &dirr->fid);
544
    Bfree(t);
545
    Bfree(t);
545
    if (dirr->dir == -1)
546
    if (dirr->dir == -1)
546
    {
547
    {
547
        Bfree(dirr);
548
        Bfree(dirr);
548
        return NULL;
549
        return NULL;
549
    }
550
    }
550
#else
551
#else
551
    dirr->dir = opendir(name);
552
    dirr->dir = opendir(name);
552
    if (dirr->dir == NULL)
553
    if (dirr->dir == NULL)
553
    {
554
    {
554
        Bfree(dirr);
555
        Bfree(dirr);
555
        return NULL;
556
        return NULL;
556
    }
557
    }
557
#endif
558
#endif
558
559
559
    dirr->status = 0;
560
    dirr->status = 0;
560
    Bstrcpy(dirr->name, name);
561
    Bstrcpy(dirr->name, name);
561
562
562
    return (BDIR *)dirr;
563
    return (BDIR *)dirr;
563
}
564
}
564
565
565
struct Bdirent *Breaddir(BDIR *dir)
566
struct Bdirent *Breaddir(BDIR *dir)
566
{
567
{
567
    BDIR_real *dirr = (BDIR_real *)dir;
568
    BDIR_real *dirr = (BDIR_real *)dir;
568
569
569
#ifdef _MSC_VER
570
#ifdef _MSC_VER
570
    if (dirr->status > 0)
571
    if (dirr->status > 0)
571
    {
572
    {
572
        if (_findnext(dirr->dir, &dirr->fid) != 0)
573
        if (_findnext(dirr->dir, &dirr->fid) != 0)
573
        {
574
        {
574
            dirr->status = -1;
575
            dirr->status = -1;
575
            return NULL;
576
            return NULL;
576
        }
577
        }
577
    }
578
    }
578
    dirr->info.namlen = Bstrlen(dirr->fid.name);
579
    dirr->info.namlen = Bstrlen(dirr->fid.name);
579
    dirr->info.name = dirr->fid.name;
580
    dirr->info.name = dirr->fid.name;
580
    dirr->status++;
581
    dirr->status++;
581
#else
582
#else
582
    struct dirent *de = readdir(dirr->dir);
583
    struct dirent *de = readdir(dirr->dir);
583
    if (de == NULL)
584
    if (de == NULL)
584
    {
585
    {
585
        dirr->status = -1;
586
        dirr->status = -1;
586
        return NULL;
587
        return NULL;
587
    }
588
    }
588
    else
589
    else
589
    {
590
    {
590
        dirr->status++;
591
        dirr->status++;
591
    }
592
    }
592
    dirr->info.namlen = Bstrlen(de->d_name);
593
    dirr->info.namlen = Bstrlen(de->d_name);
593
    dirr->info.name = de->d_name;
594
    dirr->info.name = de->d_name;
594
#endif
595
#endif
595
    dirr->info.mode = 0;
596
    dirr->info.mode = 0;
596
    dirr->info.size = 0;
597
    dirr->info.size = 0;
597
    dirr->info.mtime = 0;
598
    dirr->info.mtime = 0;
598
599
599
    char *fn = (char *)Bmalloc(Bstrlen(dirr->name) + 1 + dirr->info.namlen + 1);
600
    char *fn = (char *)Bmalloc(Bstrlen(dirr->name) + 1 + dirr->info.namlen + 1);
600
    if (fn)
601
    if (fn)
601
    {
602
    {
602
        Bsprintf(fn, "%s/%s", dirr->name, dirr->info.name);
603
        Bsprintf(fn, "%s/%s", dirr->name, dirr->info.name);
603
        struct Bstat st;
604
        struct Bstat st;
604
        if (!Bstat(fn, &st))
605
        if (!Bstat(fn, &st))
605
        {
606
        {
606
            dirr->info.mode = st.st_mode;
607
            dirr->info.mode = st.st_mode;
607
            dirr->info.size = st.st_size;
608
            dirr->info.size = st.st_size;
608
            dirr->info.mtime = st.st_mtime;
609
            dirr->info.mtime = st.st_mtime;
609
        }
610
        }
610
        Bfree(fn);
611
        Bfree(fn);
611
    }
612
    }
612
613
613
    return &dirr->info;
614
    return &dirr->info;
614
}
615
}
615
616
616
int32_t Bclosedir(BDIR *dir)
617
int32_t Bclosedir(BDIR *dir)
617
{
618
{
618
    BDIR_real *dirr = (BDIR_real *)dir;
619
    BDIR_real *dirr = (BDIR_real *)dir;
619
620
620
#ifdef _MSC_VER
621
#ifdef _MSC_VER
621
    _findclose(dirr->dir);
622
    _findclose(dirr->dir);
622
#else
623
#else
623
    closedir(dirr->dir);
624
    closedir(dirr->dir);
624
#endif
625
#endif
625
    Bfree(dirr);
626
    Bfree(dirr);
626
627
627
    return 0;
628
    return 0;
628
}
629
}
629
630
630
631
631
char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop)
632
char *Bstrtoken(char *s, const char *delim, char **ptrptr, int chop)
632
{
633
{
633
    if (!ptrptr)
634
    if (!ptrptr)
634
        return NULL;
635
        return NULL;
635
636
636
    char *p = s ? s : *ptrptr;
637
    char *p = s ? s : *ptrptr;
637
638
638
    if (!p)
639
    if (!p)
639
        return NULL;
640
        return NULL;
640
641
641
    while (*p != 0 && Bstrchr(delim, *p)) p++;
642
    while (*p != 0 && Bstrchr(delim, *p)) p++;
642
643
643
    if (*p == 0)
644
    if (*p == 0)
644
    {
645
    {
645
        *ptrptr = NULL;
646
        *ptrptr = NULL;
646
        return NULL;
647
        return NULL;
647
    }
648
    }
648
649
649
    char * const start = p;
650
    char * const start = p;
650
651
651
    while (*p != 0 && !Bstrchr(delim, *p)) p++;
652
    while (*p != 0 && !Bstrchr(delim, *p)) p++;
652
653
653
    if (*p == 0)
654
    if (*p == 0)
654
        *ptrptr = NULL;
655
        *ptrptr = NULL;
655
    else
656
    else
656
    {
657
    {
657
        if (chop)
658
        if (chop)
658
            *(p++) = 0;
659
            *(p++) = 0;
659
        *ptrptr = p;
660
        *ptrptr = p;
660
    }
661
    }
661
662
662
    return start;
663
    return start;
663
}
664
}
664
665
665
char *Bstrtolower(char *str)
666
char *Bstrtolower(char *str)
666
{
667
{
667
    if (!str)
668
    if (!str)
668
        return NULL;
669
        return NULL;
669
670
670
    int len = Bstrlen(str);
671
    int len = Bstrlen(str);
671
672
672
    if (len <= 0)
673
    if (len <= 0)
673
        return str;
674
        return str;
674
675
675
    int i = 0;
676
    int i = 0;
676
677
677
    do
678
    do
678
    {
679
    {
679
        *(str + i) = Btolower(*(str + i));
680
        *(str + i) = Btolower(*(str + i));
680
        i++;
681
        i++;
681
    } while (--len);
682
    } while (--len);
682
683
683
    return str;
684
    return str;
684
}
685
}
685
686
686
687
687
//Brute-force case-insensitive, slash-insensitive, * and ? wildcard matcher
688
//Brute-force case-insensitive, slash-insensitive, * and ? wildcard matcher
688
//Returns: 1:matches, 0:doesn't match
689
//Returns: 1:matches, 0:doesn't match
689
#ifndef WITHKPLIB
690
#ifndef WITHKPLIB
690
extern char toupperlookup[256];
691
extern char toupperlookup[256];
691
692
692
static int32_t wildmatch(const char *match, const char *wild)
693
static int32_t wildmatch(const char *match, const char *wild)
693
{
694
{
694
    do
695
    do
695
    {
696
    {
696
        if (*match && (toupperlookup[*wild] == toupperlookup[*match] || *wild == '?'))
697
        if (*match && (toupperlookup[*wild] == toupperlookup[*match] || *wild == '?'))
697
        {
698
        {
698
            wild++, match++;
699
            wild++, match++;
699
            continue;
700
            continue;
700
        }
701
        }
701
        else if ((*match|*wild) == '\0')
702
        else if ((*match|*wild) == '\0')
702
            return 1;
703
            return 1;
703
        else if (*wild == '*')
704
        else if (*wild == '*')
704
        {
705
        {
705
            do { wild++; } while (*wild == '*');
706
            do { wild++; } while (*wild == '*');
706
            do
707
            do
707
            {
708
            {
708
                if (*wild == '\0')
709
                if (*wild == '\0')
709
                    return 1;
710
                    return 1;
710
                while (*match && toupperlookup[*match] != toupperlookup[*wild]) match++;
711
                while (*match && toupperlookup[*match] != toupperlookup[*wild]) match++;
711
                if (*match && *(match+1) && toupperlookup[*(match+1)] != toupperlookup[*(wild+1)])
712
                if (*match && *(match+1) && toupperlookup[*(match+1)] != toupperlookup[*(wild+1)])
712
                {
713
                {
713
                    match++;
714
                    match++;
714
                    continue;
715
                    continue;
715
                }
716
                }
716
                break;
717
                break;
717
            }
718
            }
718
            while (1);
719
            while (1);
719
            if (toupperlookup[*match] == toupperlookup[*wild])
720
            if (toupperlookup[*match] == toupperlookup[*wild])
720
                continue;
721
                continue;
721
        }
722
        }
722
        return 0;
723
        return 0;
723
    }
724
    }
724
    while (1);
725
    while (1);
725
}
726
}
726
#endif
727
#endif
727
728
728
#if !defined(_WIN32)
729
#if !defined(_WIN32)
729
char *Bstrlwr(char *s)
730
char *Bstrlwr(char *s)
730
{
731
{
731
    if (!s) return s;
732
    if (!s) return s;
732
    char *t = s;
733
    char *t = s;
733
    while (*t) { *t = Btolower(*t); t++; }
734
    while (*t) { *t = Btolower(*t); t++; }
734
    return s;
735
    return s;
735
}
736
}
736
737
737
char *Bstrupr(char *s)
738
char *Bstrupr(char *s)
738
{
739
{
739
    if (!s) return s;
740
    if (!s) return s;
740
    char *t = s;
741
    char *t = s;
741
    while (*t) { *t = Btoupper(*t); t++; }
742
    while (*t) { *t = Btoupper(*t); t++; }
742
    return s;
743
    return s;
743
}
744
}
744
#endif
745
#endif
745
746
746
747
747
//
748
//
748
// Bgetsysmemsize() -- gets the amount of system memory in the machine
749
// Bgetsysmemsize() -- gets the amount of system memory in the machine
749
//
750
//
750
#ifdef _WIN32
751
#ifdef _WIN32
751
typedef BOOL (WINAPI *aGlobalMemoryStatusExType)(LPMEMORYSTATUSEX);
752
typedef BOOL (WINAPI *aGlobalMemoryStatusExType)(LPMEMORYSTATUSEX);
752
#endif
753
#endif
753
754
754
uint32_t Bgetsysmemsize(void)
755
uint32_t Bgetsysmemsize(void)
755
{
756
{
756
#ifdef _WIN32
757
#ifdef _WIN32
757
    uint32_t siz = UINT32_MAX;
758
    uint32_t siz = UINT32_MAX;
758
    HMODULE lib = LoadLibrary("KERNEL32.DLL");
759
    HMODULE lib = LoadLibrary("KERNEL32.DLL");
759
760
760
    if (lib)
761
    if (lib)
761
    {
762
    {
762
        aGlobalMemoryStatusExType aGlobalMemoryStatusEx =
763
        aGlobalMemoryStatusExType aGlobalMemoryStatusEx =
763
            (aGlobalMemoryStatusExType)GetProcAddress(lib, "GlobalMemoryStatusEx");
764
            (aGlobalMemoryStatusExType)GetProcAddress(lib, "GlobalMemoryStatusEx");
764
765
765
        if (aGlobalMemoryStatusEx)
766
        if (aGlobalMemoryStatusEx)
766
        {
767
        {
767
            //WinNT
768
            //WinNT
768
            MEMORYSTATUSEX memst;
769
            MEMORYSTATUSEX memst;
769
            memst.dwLength = sizeof(MEMORYSTATUSEX);
770
            memst.dwLength = sizeof(MEMORYSTATUSEX);
770
            if (aGlobalMemoryStatusEx(&memst))
771
            if (aGlobalMemoryStatusEx(&memst))
771
                siz = (uint32_t)min(UINT32_MAX, memst.ullTotalPhys);
772
                siz = (uint32_t)min(UINT32_MAX, memst.ullTotalPhys);
772
        }
773
        }
773
        else
774
        else
774
        {
775
        {
775
            // Yeah, there's enough Win9x hatred here that a perfectly good workaround
776
            // Yeah, there's enough Win9x hatred here that a perfectly good workaround
776
            // has been replaced by an error message.  Oh well, we don't support 9x anyway.
777
            // has been replaced by an error message.  Oh well, we don't support 9x anyway.
777
            initprintf("Bgetsysmemsize(): error determining system memory size!\n");
778
            initprintf("Bgetsysmemsize(): error determining system memory size!\n");
778
        }
779
        }
779
780
780
        FreeLibrary(lib);
781
        FreeLibrary(lib);
781
    }
782
    }
782
783
783
    return siz;
784
    return siz;
784
#elif (defined(_SC_PAGE_SIZE) || defined(_SC_PAGESIZE)) && defined(_SC_PHYS_PAGES) && !defined(GEKKO)
785
#elif (defined(_SC_PAGE_SIZE) || defined(_SC_PAGESIZE)) && defined(_SC_PHYS_PAGES) && !defined(GEKKO)
785
    uint32_t siz = UINT32_MAX;
786
    uint32_t siz = UINT32_MAX;
786
    int64_t scpagesiz, scphyspages;
787
    int64_t scpagesiz, scphyspages;
787
788
788
#ifdef _SC_PAGE_SIZE
789
#ifdef _SC_PAGE_SIZE
789
    scpagesiz = sysconf(_SC_PAGE_SIZE);
790
    scpagesiz = sysconf(_SC_PAGE_SIZE);
790
#else
791
#else
791
    scpagesiz = sysconf(_SC_PAGESIZE);
792
    scpagesiz = sysconf(_SC_PAGESIZE);
792
#endif
793
#endif
793
    scphyspages = sysconf(_SC_PHYS_PAGES);
794
    scphyspages = sysconf(_SC_PHYS_PAGES);
794
    if (scpagesiz >= 0 && scphyspages >= 0)
795
    if (scpagesiz >= 0 && scphyspages >= 0)
795
        siz = (uint32_t)min(UINT32_MAX, (int64_t)scpagesiz * (int64_t)scphyspages);
796
        siz = (uint32_t)min(UINT32_MAX, (int64_t)scpagesiz * (int64_t)scphyspages);
796
797
797
    //initprintf("Bgetsysmemsize(): %d pages of %d bytes, %d bytes of system memory\n",
798
    //initprintf("Bgetsysmemsize(): %d pages of %d bytes, %d bytes of system memory\n",
798
    //          scphyspages, scpagesiz, siz);
799
    //          scphyspages, scpagesiz, siz);
799
800
800
    return siz;
801
    return siz;
801
#else
802
#else
802
    return UINT32_MAX;
803
    return UINT32_MAX;
803
#endif
804
#endif
804
}
805
}
805
806
806
#ifdef GEKKO
807
#ifdef GEKKO
807
int access(const char *pathname, int mode)
808
int access(const char *pathname, int mode)
808
{
809
{
809
    struct stat st;
810
    struct stat st;
810
    if (stat(pathname, &st)==-1)
811
    if (stat(pathname, &st)==-1)
811
        return -1;
812
        return -1;
812
813
813
    // TODO: Check mode against st_mode
814
    // TODO: Check mode against st_mode
814
    UNREFERENCED_PARAMETER(mode);
815
    UNREFERENCED_PARAMETER(mode);
815
816
816
    return 0;
817
    return 0;
817
}
818
}
818
#endif
819
#endif
819
820
820
#define LIBDIVIDE_BODY
821
#define LIBDIVIDE_BODY
821
#include "libdivide.h"
822
#include "libdivide.h"
822
823
823
 
824