2009-02-15 06:10:59 +00:00
|
|
|
/***************************************************************************
|
|
|
|
tools.c Copyright (C) 1999,2000,2001,2002 Christoph Reichenbach
|
|
|
|
|
|
|
|
This program may be modified and copied freely according to the terms of
|
|
|
|
the GNU general public license (GPL), as long as the above copyright
|
|
|
|
notice and the licensing information contained herein are preserved.
|
|
|
|
|
|
|
|
Please refer to www.gnu.org for licensing details.
|
|
|
|
|
|
|
|
This work is provided AS IS, without warranty of any kind, expressed or
|
|
|
|
implied, including but not limited to the warranties of merchantibility,
|
|
|
|
noninfringement, and fitness for a specific purpose. The author will not
|
|
|
|
be held liable for any damage caused by this work or derivatives of it.
|
|
|
|
|
|
|
|
By using this source code, you agree to the licensing terms as stated
|
|
|
|
above.
|
|
|
|
|
|
|
|
|
|
|
|
Please contact the maintainer for bug reports or inquiries.
|
|
|
|
|
|
|
|
Current Maintainer:
|
|
|
|
|
|
|
|
Christoph Reichenbach (CJR) [jameson@linuxgames.com]
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
2009-02-16 00:34:40 +00:00
|
|
|
#include "common/scummsys.h"
|
|
|
|
#include "common/str.h"
|
2009-02-15 20:54:20 +00:00
|
|
|
|
2009-02-15 21:11:25 +00:00
|
|
|
#ifdef UNIX
|
2009-02-15 20:54:20 +00:00
|
|
|
#define _GNU_SOURCE /* For FNM_CASEFOLD in fnmatch.h */
|
|
|
|
#include <fnmatch.h>
|
|
|
|
#endif
|
|
|
|
|
2009-02-15 08:34:13 +00:00
|
|
|
#include "sci/include/engine.h"
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
# include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
# include <sys/timeb.h>
|
|
|
|
# include <windows.h>
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
2009-02-15 10:04:29 +00:00
|
|
|
#endif
|
|
|
|
|
2009-02-15 21:11:25 +00:00
|
|
|
#ifdef WIN32
|
2009-02-15 10:04:29 +00:00
|
|
|
# include <windows.h>
|
2009-02-15 10:21:22 +00:00
|
|
|
# include <mmsystem.h>
|
2009-02-15 10:04:29 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
void usleep(long usec);
|
2009-02-15 10:04:29 +00:00
|
|
|
|
2009-02-15 09:56:04 +00:00
|
|
|
# ifdef sleep
|
|
|
|
# undef sleep
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# define sleep(x) \
|
|
|
|
do { \
|
|
|
|
if (x == 0) { \
|
|
|
|
Sleep(0); \
|
|
|
|
} else { \
|
|
|
|
if (timeBeginPeriod(1) != TIMERR_NOERROR) \
|
|
|
|
fprintf(stderr, "timeBeginPeriod(1) failed\n"); \
|
|
|
|
Sleep(x); \
|
|
|
|
if (timeEndPeriod(1) != TIMERR_NOERROR) \
|
|
|
|
fprintf(stderr, "timeEndPeriod(1) failed\n"); \
|
|
|
|
} \
|
|
|
|
} while (0);
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
2009-02-15 10:04:29 +00:00
|
|
|
|
2009-02-15 21:27:42 +00:00
|
|
|
#ifdef __DC__
|
2009-02-15 06:10:59 +00:00
|
|
|
# include <kos/thread.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_MEMFROB
|
|
|
|
void *memfrob(void *s, size_t n);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int script_debug_flag = 0; /* Defaulting to running mode */
|
|
|
|
int sci_debug_flags = 0; /* Special flags */
|
|
|
|
|
|
|
|
#ifndef con_file
|
|
|
|
# define con_file 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MEMTEST_HARDNESS 31
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
memtest(const char *file, int line) {
|
2009-02-15 06:10:59 +00:00
|
|
|
/* va_list argp; -- unused */
|
|
|
|
int i;
|
|
|
|
void *blocks[MEMTEST_HARDNESS + 1];
|
2009-02-15 22:28:50 +00:00
|
|
|
fprintf(stderr, "Memtesting in %s, L%d\n", file, line);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++) {
|
|
|
|
blocks[i] = sci_malloc(1 + i);
|
|
|
|
#ifdef HAVE_MEMFROB
|
|
|
|
memfrob(blocks[i], 1 + i);
|
|
|
|
#else
|
|
|
|
memset(blocks[i], 42, 1 + i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++)
|
|
|
|
free(blocks[i]);
|
|
|
|
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++) {
|
2009-02-15 22:28:50 +00:00
|
|
|
blocks[i] = sci_malloc(5 + i * 5);
|
2009-02-15 06:10:59 +00:00
|
|
|
#ifdef HAVE_MEMFROB
|
|
|
|
memfrob(blocks[i], 5 + i*5);
|
|
|
|
#else
|
|
|
|
memset(blocks[i], 42, 5 + i*5);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++)
|
|
|
|
free(blocks[i]);
|
|
|
|
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++) {
|
2009-02-15 22:28:50 +00:00
|
|
|
blocks[i] = sci_malloc(5 + i * 100);
|
2009-02-15 06:10:59 +00:00
|
|
|
#ifdef HAVE_MEMFROB
|
|
|
|
memfrob(blocks[i], 5 + i*100);
|
|
|
|
#else
|
|
|
|
memset(blocks[i], 42, 5 + i*100);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++)
|
|
|
|
free(blocks[i]);
|
|
|
|
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++) {
|
2009-02-15 22:28:50 +00:00
|
|
|
blocks[i] = sci_malloc(5 + i * 1000);
|
2009-02-15 06:10:59 +00:00
|
|
|
#ifdef HAVE_MEMFROB
|
|
|
|
memfrob(blocks[i], 5 + i * 1000);
|
|
|
|
#else
|
|
|
|
memset(blocks[i], 42, 5 + i * 1000);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
for (i = 0; i < MEMTEST_HARDNESS; i++)
|
|
|
|
free(blocks[i]);
|
2009-02-15 22:28:50 +00:00
|
|
|
fprintf(stderr, "Memtest succeeded!\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2009-02-15 22:28:50 +00:00
|
|
|
memdup(void *src, int size) {
|
2009-02-15 06:10:59 +00:00
|
|
|
void *b = malloc(size);
|
|
|
|
memcpy(b, src, size);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
int sci_ffs(int _mask) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
if (!_mask) return 0;
|
|
|
|
retval++;
|
2009-02-15 22:28:50 +00:00
|
|
|
while (!(_mask & 1)) {
|
2009-02-15 06:10:59 +00:00
|
|
|
retval++;
|
|
|
|
_mask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************** Debug functions ********************/
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
_SCIkvprintf(FILE *file, const char *format, va_list args) {
|
2009-02-15 06:10:59 +00:00
|
|
|
vfprintf(file, format, args);
|
|
|
|
if (con_file) vfprintf(con_file, format, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
_SCIkprintf(FILE *file, const char *format, ...) {
|
2009-02-15 06:10:59 +00:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
_SCIkvprintf(file, format, args);
|
2009-02-15 22:28:50 +00:00
|
|
|
va_end(args);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
_SCIkwarn(state_t *s, const char *file, int line, int area, const char *format, ...) {
|
2009-02-15 06:10:59 +00:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
if (area == SCIkERROR_NR)
|
|
|
|
_SCIkprintf(stderr, "ERROR: ");
|
|
|
|
else
|
|
|
|
_SCIkprintf(stderr, "Warning: ");
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
_SCIkvprintf(stderr, format, args);
|
|
|
|
va_end(args);
|
|
|
|
fflush(NULL);
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (sci_debug_flags & _DEBUG_FLAG_BREAK_ON_WARNINGS) script_debug_flag = 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
_SCIkdebug(state_t *s, const char *file, int line, int area, const char *format, ...) {
|
2009-02-15 06:10:59 +00:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
if (s->debug_mode & (1 << area)) {
|
|
|
|
_SCIkprintf(stdout, " kernel: (%s L%d): ", file, line);
|
|
|
|
va_start(args, format);
|
|
|
|
_SCIkvprintf(stdout, format, args);
|
|
|
|
va_end(args);
|
|
|
|
fflush(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
_SCIGNUkdebug(const char *funcname, state_t *s, const char *file, int line, int area, const char *format, ...) {
|
2009-02-15 06:10:59 +00:00
|
|
|
va_list xargs;
|
|
|
|
int error = ((area == SCIkWARNING_NR) || (area == SCIkERROR_NR));
|
|
|
|
|
|
|
|
if (error || (s->debug_mode & (1 << area))) { /* Is debugging enabled for this area? */
|
|
|
|
|
|
|
|
_SCIkprintf(stderr, "FSCI: ");
|
|
|
|
|
|
|
|
if (area == SCIkERROR_NR)
|
|
|
|
_SCIkprintf(stderr, "ERROR in %s ", funcname);
|
|
|
|
else if (area == SCIkWARNING_NR)
|
|
|
|
_SCIkprintf(stderr, "%s: Warning ", funcname);
|
|
|
|
else _SCIkprintf(stderr, funcname);
|
|
|
|
|
|
|
|
_SCIkprintf(stderr, "(%s L%d): ", file, line);
|
|
|
|
|
|
|
|
va_start(xargs, format);
|
|
|
|
_SCIkvprintf(stderr, format, xargs);
|
|
|
|
va_end(xargs);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_GETTIMEOFDAY)
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_gettime(long *seconds, long *useconds) {
|
2009-02-15 06:10:59 +00:00
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
assert(!gettimeofday(&tv, NULL));
|
|
|
|
*seconds = tv.tv_sec;
|
|
|
|
*useconds = tv.tv_usec;
|
|
|
|
}
|
2009-02-15 21:11:25 +00:00
|
|
|
#elif defined (WIN32)
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
/*WARNING(Incorrect)*/
|
|
|
|
/* Warning: This function only retrieves the amount of mseconds since the start of
|
|
|
|
** the Win32 kernel; it does /not/ provide the number of seconds since the epoch!
|
|
|
|
** There are no known cases where this causes problems, though. */
|
2009-02-15 22:28:50 +00:00
|
|
|
void sci_gettime(long *seconds, long *useconds) {
|
2009-02-15 06:10:59 +00:00
|
|
|
DWORD tm;
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (TIMERR_NOERROR != timeBeginPeriod(1)) {
|
2009-02-15 06:10:59 +00:00
|
|
|
fprintf(stderr, "timeBeginPeriod(1) failed in sci_gettime\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
tm = timeGetTime();
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (TIMERR_NOERROR != timeEndPeriod(1)) {
|
2009-02-15 06:10:59 +00:00
|
|
|
fprintf(stderr, "timeEndPeriod(1) failed in sci_gettime\n");
|
|
|
|
}
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
*seconds = tm / 1000;
|
|
|
|
*useconds = (tm % 1000) * 1000;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
# error "You need to provide a microsecond resolution sci_gettime implementation for your platform!"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_get_current_time(GTimeVal *val) {
|
2009-02-15 06:10:59 +00:00
|
|
|
long foo, bar;
|
|
|
|
sci_gettime(&foo, &bar);
|
|
|
|
val->tv_sec = foo;
|
|
|
|
val->tv_usec = bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************* Directory entities *************/
|
2009-02-15 21:11:25 +00:00
|
|
|
#if defined(WIN32)
|
2009-02-15 06:10:59 +00:00
|
|
|
/******** Dir: Win32 CODE ********/
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_init_dir(sci_dir_t *dir) {
|
2009-02-15 06:10:59 +00:00
|
|
|
dir->search = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_find_first(sci_dir_t *dir, const char *mask) {
|
2009-02-15 06:10:59 +00:00
|
|
|
dir->search = _findfirst(mask, &(dir->fileinfo));
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (dir->search != -1) {
|
|
|
|
if (dir->fileinfo.name == NULL) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(dir->fileinfo.name, ".") == 0 ||
|
2009-02-15 22:28:50 +00:00
|
|
|
strcmp(dir->fileinfo.name, "..") == 0) {
|
|
|
|
if (sci_find_next(dir) == NULL) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dir->fileinfo.name;
|
2009-02-15 22:28:50 +00:00
|
|
|
} else {
|
|
|
|
switch (errno) {
|
|
|
|
case ENOENT: {
|
2009-02-15 06:10:59 +00:00
|
|
|
#ifdef _DEBUG
|
2009-02-15 22:28:50 +00:00
|
|
|
printf("_findfirst errno = ENOENT: no match\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (mask)
|
|
|
|
printf(" in: %s\n", mask);
|
|
|
|
else
|
|
|
|
printf(" - searching in undefined directory\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
2009-02-15 22:28:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EINVAL: {
|
|
|
|
printf("_findfirst errno = EINVAL: invalid filename\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
printf("_findfirst errno = unknown (%d)", errno);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_find_next(sci_dir_t *dir) {
|
|
|
|
if (dir->search == -1)
|
|
|
|
return NULL;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (_findnext(dir->search, &(dir->fileinfo)) < 0) {
|
|
|
|
_findclose(dir->search);
|
|
|
|
dir->search = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (strcmp(dir->fileinfo.name, ".") == 0 ||
|
|
|
|
strcmp(dir->fileinfo.name, "..") == 0) {
|
|
|
|
if (sci_find_next(dir) == NULL) {
|
|
|
|
return NULL;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-15 22:28:50 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
return dir->fileinfo.name;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_finish_find(sci_dir_t *dir) {
|
|
|
|
if (dir->search != -1) {
|
|
|
|
_findclose(dir->search);
|
2009-02-15 06:10:59 +00:00
|
|
|
dir->search = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-15 21:11:25 +00:00
|
|
|
#else /* !WIN32 */
|
2009-02-15 06:10:59 +00:00
|
|
|
/******** Dir: UNIX CODE ********/
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_init_dir(sci_dir_t *dir) {
|
2009-02-15 06:10:59 +00:00
|
|
|
dir->dir = NULL;
|
|
|
|
dir->mask_copy = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_find_first(sci_dir_t *dir, const char *mask) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (dir->dir)
|
|
|
|
closedir(dir->dir);
|
|
|
|
|
|
|
|
if (!(dir->dir = opendir("."))) {
|
|
|
|
sciprintf("%s, L%d: opendir(\".\") failed!\n", __FILE__, __LINE__);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
dir->mask_copy = sci_strdup(mask);
|
|
|
|
|
|
|
|
return sci_find_next(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef FNM_CASEFOLD
|
|
|
|
#define FNM_CASEFOLD 0
|
|
|
|
#warning "File searches will not be case-insensitive!"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_find_next(sci_dir_t *dir) {
|
2009-02-15 06:10:59 +00:00
|
|
|
struct dirent *match;
|
|
|
|
|
|
|
|
while ((match = readdir(dir->dir))) {
|
|
|
|
if (match->d_name[0] == '.')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!fnmatch(dir->mask_copy, match->d_name, FNM_CASEFOLD))
|
|
|
|
return match->d_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
sci_finish_find(dir);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_finish_find(sci_dir_t *dir) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (dir->dir) {
|
|
|
|
closedir(dir->dir);
|
|
|
|
dir->dir = NULL;
|
|
|
|
free(dir->mask_copy);
|
|
|
|
dir->mask_copy = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-15 21:11:25 +00:00
|
|
|
#endif /* !WIN32 */
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
/************* /Directory entities *************/
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_mkpath(const char *path) {
|
2009-02-15 06:10:59 +00:00
|
|
|
const char *path_position = path;
|
2009-02-15 22:28:50 +00:00
|
|
|
char *next_separator = NULL;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (chdir(G_DIR_SEPARATOR_S)) { /* Go to root */
|
|
|
|
sciprintf("Error: Could not change to root directory '%s'!\n",
|
|
|
|
G_DIR_SEPARATOR_S);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
do {
|
|
|
|
if (next_separator)
|
|
|
|
*next_separator = G_DIR_SEPARATOR_S[0];
|
|
|
|
next_separator = (char *)strchr(path_position, G_DIR_SEPARATOR_S[0]);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
if (next_separator)
|
|
|
|
*next_separator = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (*path_position) { /* Unless we're at the first slash... */
|
|
|
|
if (chdir(path_position)) {
|
|
|
|
if (scimkdir(path_position, 0700) || chdir(path_position)) {
|
|
|
|
sciprintf("Error: Could not create subdirectory '%s' in",
|
2009-02-15 22:28:50 +00:00
|
|
|
path_position);
|
2009-02-15 06:10:59 +00:00
|
|
|
if (next_separator)
|
|
|
|
*next_separator = G_DIR_SEPARATOR_S[0];
|
|
|
|
sciprintf(" '%s'!\n", path);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path_position = next_separator + 1;
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
} while (next_separator);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
return 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_get_homedir(void) {
|
2009-02-15 21:11:25 +00:00
|
|
|
#ifdef WIN32
|
2009-02-15 06:10:59 +00:00
|
|
|
char *_path_buf = (char*)malloc(MAX_PATH);
|
|
|
|
char *dr = getenv("HOMEDRIVE");
|
|
|
|
char *path = getenv("HOMEPATH");
|
|
|
|
|
|
|
|
if (!dr || !path)
|
|
|
|
return getenv("WINDIR");
|
|
|
|
|
|
|
|
strncpy(_path_buf, dr, 4);
|
|
|
|
strncat(_path_buf, path, MAX_PATH - 4);
|
|
|
|
|
|
|
|
return _path_buf;
|
|
|
|
#elif defined(__unix__) || !defined(X_DISPLAY_MISSING) || defined (__BEOS__) || defined(MACOSX)
|
|
|
|
return getenv("HOME");
|
2009-02-15 21:27:42 +00:00
|
|
|
#elif defined(__DC__)
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
#elif defined(__amigaos4__)
|
|
|
|
return "/PROGDIR/";
|
|
|
|
#else
|
|
|
|
# error Please add a $HOME policy for your platform!
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sci_queue_t *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_init_queue(sci_queue_t *queue) {
|
2009-02-15 06:10:59 +00:00
|
|
|
queue->start = queue->end = NULL;
|
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
sci_queue_t *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_add_to_queue(sci_queue_t *queue, void *data, int type) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sci_queue_node_t *node = (sci_queue_node_t*)sci_malloc(sizeof(sci_queue_node_t));
|
|
|
|
|
|
|
|
node->next = NULL;
|
|
|
|
node->data = data;
|
|
|
|
node->type = type;
|
|
|
|
|
|
|
|
if (queue->start)
|
|
|
|
queue->start->next = node;
|
|
|
|
|
|
|
|
queue->start = node;
|
|
|
|
|
|
|
|
if (!queue->end)
|
|
|
|
queue->end = node;
|
|
|
|
|
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_get_from_queue(sci_queue_t *queue, int *type) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sci_queue_node_t *node = queue->end;
|
|
|
|
if (node) {
|
|
|
|
void *retval = node->data;
|
|
|
|
if (type)
|
|
|
|
*type = node->type;
|
|
|
|
|
|
|
|
queue->end = node->next;
|
|
|
|
|
|
|
|
if (queue->end == NULL) /* Queue empty? */
|
|
|
|
queue->start = NULL;
|
|
|
|
|
|
|
|
free(node);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-- Yielding to the scheduler --*/
|
|
|
|
|
|
|
|
#ifdef HAVE_SCHED_YIELD
|
|
|
|
# include <sched.h>
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_sched_yield(void) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sched_yield();
|
|
|
|
}
|
|
|
|
|
2009-02-15 21:27:42 +00:00
|
|
|
#elif defined (__DC__)
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_sched_yield() {
|
2009-02-15 06:10:59 +00:00
|
|
|
thd_pass();
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined (__BEOS__)
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_sched_yield() {
|
2009-02-15 06:10:59 +00:00
|
|
|
snooze(0);
|
|
|
|
}
|
|
|
|
|
2009-02-15 21:11:25 +00:00
|
|
|
#elif defined (WIN32)
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_sched_yield() {
|
2009-02-15 06:10:59 +00:00
|
|
|
sleep(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
void
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_sched_yield() {
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* !HAVE_SCHED_YIELD */
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
_fcaseseek(const char *fname, sci_dir_t *dir)
|
|
|
|
/* Expects *dir to be uninitialized and the caller to
|
|
|
|
** free it afterwards */
|
|
|
|
{
|
|
|
|
char *buf, *iterator;
|
|
|
|
char _buf[14];
|
|
|
|
char *retval = NULL, *name;
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
2009-02-15 12:29:09 +00:00
|
|
|
return (char *)fname;
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (strchr(fname, G_DIR_SEPARATOR)) {
|
|
|
|
fprintf(stderr, "_fcaseseek() does not support subdirs\n");
|
|
|
|
BREAKPOINT();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(fname) > 12) /* not a DOS file? */
|
|
|
|
buf = (char*)sci_malloc(strlen(fname) + 1);
|
|
|
|
else
|
|
|
|
buf = _buf;
|
|
|
|
|
|
|
|
sci_init_dir(dir);
|
|
|
|
|
|
|
|
/* Replace all letters with '?' chars */
|
|
|
|
strcpy(buf, fname);
|
|
|
|
iterator = buf;
|
|
|
|
while (*iterator) {
|
|
|
|
if (isalpha(*iterator))
|
|
|
|
*iterator = '?';
|
|
|
|
iterator++;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = sci_find_first(dir, buf);
|
|
|
|
|
|
|
|
while (name && !retval) {
|
|
|
|
if (!strcasecmp(fname, name))
|
|
|
|
retval = name;
|
|
|
|
else
|
|
|
|
name = sci_find_next(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(fname) > 12)
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FILE *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_fopen(const char *fname, const char *mode) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sci_dir_t dir;
|
|
|
|
char *name = _fcaseseek(fname, &dir);
|
|
|
|
FILE *file = NULL;
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
file = fopen(name, mode);
|
|
|
|
else if (strchr(mode, 'w'))
|
|
|
|
file = fopen(fname, mode);
|
|
|
|
|
|
|
|
sci_finish_find(&dir); /* Free memory */
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_open(const char *fname, int flags) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sci_dir_t dir;
|
|
|
|
char *name;
|
|
|
|
int file = SCI_INVALID_FD;
|
|
|
|
char *separator_position;
|
|
|
|
char *path;
|
|
|
|
char *caller_cwd;
|
|
|
|
|
|
|
|
sci_init_dir(&dir);
|
|
|
|
|
|
|
|
separator_position = (char *)strrchr(fname, G_DIR_SEPARATOR);
|
2009-02-15 22:28:50 +00:00
|
|
|
if (separator_position) {
|
|
|
|
path = (char *) malloc(separator_position - fname + 1);
|
2009-02-15 06:10:59 +00:00
|
|
|
path[separator_position-fname] = 0;
|
2009-02-15 22:28:50 +00:00
|
|
|
strncpy(path, fname, separator_position - fname);
|
2009-02-15 06:10:59 +00:00
|
|
|
chdir(path);
|
|
|
|
free(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
name = _fcaseseek(separator_position ? separator_position + 1 : fname, &dir);
|
|
|
|
if (name)
|
|
|
|
file = open(name, flags);
|
|
|
|
|
|
|
|
sci_finish_find(&dir); /* Free memory */
|
|
|
|
|
|
|
|
caller_cwd = sci_getcwd();
|
|
|
|
chdir(caller_cwd);
|
|
|
|
free(caller_cwd);
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_getcwd(void) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int size = 0;
|
|
|
|
char *cwd = NULL;
|
|
|
|
|
|
|
|
while (size < 8192) {
|
|
|
|
size += 256;
|
|
|
|
cwd = (char*)sci_malloc(size);
|
2009-02-15 22:28:50 +00:00
|
|
|
if (getcwd(cwd, size - 1))
|
2009-02-15 06:10:59 +00:00
|
|
|
return cwd;
|
|
|
|
|
|
|
|
sci_free(cwd);
|
|
|
|
}
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
fprintf(stderr, "Could not determine current working directory!\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-02-15 21:27:42 +00:00
|
|
|
#ifdef __DC__
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_fd_size(int fd) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return fs_total(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_file_size(const char *fname) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int fd = fs_open(fname, O_RDONLY);
|
|
|
|
int retval = -1;
|
|
|
|
|
|
|
|
if (fd != 0) {
|
|
|
|
retval = sci_fd_size(fd);
|
|
|
|
fs_close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_fd_size(int fd) {
|
2009-02-15 06:10:59 +00:00
|
|
|
struct stat fd_stat;
|
|
|
|
if (fstat(fd, &fd_stat)) return -1;
|
|
|
|
return fd_stat.st_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-02-15 22:28:50 +00:00
|
|
|
sci_file_size(const char *fname) {
|
2009-02-15 06:10:59 +00:00
|
|
|
struct stat fn_stat;
|
|
|
|
if (stat(fname, &fn_stat)) return -1;
|
|
|
|
return fn_stat.st_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Simple heuristic to work around array handling peculiarity in SQ4:
|
|
|
|
It uses StrAt() to read the individual elements, so we must determine
|
|
|
|
whether a string is really a string or an array. */
|
2009-02-15 22:28:50 +00:00
|
|
|
int is_print_str(char *str) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int printable = 0;
|
|
|
|
int len = strlen(str);
|
2009-02-15 22:28:50 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
if (len == 0) return 1;
|
|
|
|
|
2009-02-15 22:28:50 +00:00
|
|
|
while (*str) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (isprint(*str)) printable++;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((float) printable / (float) len >= 0.5);
|
|
|
|
}
|