This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/os/sysbits.c

3890 lines
92 KiB
C
Raw Normal View History

/*************************************************************************
2015-04-24 17:03:44 +01:00
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
2015-07-06 12:03:16 +01:00
* PrologPathProkoh
2015-04-24 17:03:44 +01:00
* *
* File: sysbits.c *
* Last rev: 4/03/88 *
* mods: *
* comments: very much machine dependent routines *
* *
*************************************************************************/
#ifdef SCCS
static char SccsId[] = "%W% %G%";
#endif
2015-01-04 23:58:23 +00:00
// @{
2014-09-11 20:06:57 +01:00
/**
@addtogroup YAPOS
*/
/*
* In this routine we shall try to include the inevitably machine dependant
* routines. These include, for the moment : Time, A rudimentary form of
* signal handling, OS calls,
*
* Vitor Santos Costa, February 1987
*
*/
/* windows.h does not like absmi.h, this
should fix it for now */
#if _WIN32 || __MINGW32__
#include <winsock2.h>
#endif
#include "absmi.h"
#include "yapio.h"
#include "alloc.h"
#include <math.h>
#if STDC_HEADERS
#include <stdlib.h>
#endif
#if HAVE_WINDOWS_H
#include <windows.h>
#endif
#if HAVE_SYS_TIME_H && !_MSC_VER
#include <sys/time.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_WAIT_H && !defined(__MINGW32__) && !_MSC_VER
#include <sys/wait.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if !HAVE_STRNCAT
#define strncat(X,Y,Z) strcat(X,Y)
#endif
#if !HAVE_STRNCPY
#define strncpy(X,Y,Z) strcpy(X,Y)
#endif
#if HAVE_GETPWNAM
#include <pwd.h>
#endif
2014-03-04 12:02:26 +00:00
#include <ctype.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if _MSC_VER || defined(__MINGW32__)
#include <windows.h>
/* required for DLL compatibility */
#if HAVE_DIRECT_H
#include <direct.h>
#endif
#include <io.h>
#include <shlwapi.h>
#else
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#endif
2012-04-18 20:14:56 +01:00
/* CYGWIN seems to include this automatically */
#if HAVE_FENV_H && !defined(__CYGWIN__)
#include <fenv.h>
#endif
2015-04-15 15:07:04 +01:00
#if defined(ENABLE_SYSTEM_EXPANSION) && HAVE_WORDEXP_H
#include <wordexp.h>
#endif
#if HAVE_LIBGEN_H
#include <libgen.h>
#endif
2015-10-20 08:01:20 +01:00
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#if HAVE_READLINE_READLINE_H
#include <readline/readline.h>
#endif
2015-04-13 13:28:17 +01:00
/// File Error Handler
static void
Yap_FileError(yap_error_number type, Term where, const char *format,...)
{
2015-07-06 12:03:16 +01:00
2015-06-17 23:49:02 +01:00
if ( trueLocalPrologFlag(FILEERRORS_FLAG) ) {
va_list ap;
2015-04-13 13:28:17 +01:00
va_start (ap, format);
/* now build the error string */
Yap_Error(type, TermNil, format, ap);
va_end (ap);
}
}
2015-04-13 13:28:17 +01:00
2013-04-25 23:15:04 +01:00
static void InitTime(int);
static void InitWTime(void);
static Int p_sh( USES_REGS1 );
static Int p_shell( USES_REGS1 );
static Int p_system( USES_REGS1 );
static Int p_mv( USES_REGS1 );
static Int p_dir_sp( USES_REGS1 );
static void InitRandom(void);
static Int p_alarm( USES_REGS1 );
static Int p_getenv( USES_REGS1 );
static Int p_putenv( USES_REGS1 );
2015-10-18 12:28:02 +01:00
static bool set_fpu_exceptions(Term);
2015-06-17 23:49:02 +01:00
static char *expandVars(const char *pattern, char *expanded, int maxlen);
#ifdef MACYAP
2013-04-25 23:15:04 +01:00
static int chdir(char *);
/* #define signal skel_signal */
#endif /* MACYAP */
2013-04-25 23:15:04 +01:00
void exit(int);
2014-11-05 07:45:36 +00:00
#ifdef __WINDOWS__
2010-04-07 01:35:44 +01:00
void
Yap_WinError(char *yap_error)
{
char msg[256];
/* Error, we could not read time */
2015-04-24 17:03:44 +01:00
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg, 256,
NULL);
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "%s at %s", msg, yap_error);
}
2014-11-09 12:06:40 +00:00
#endif /* __WINDOWS__ */
#define is_valid_env_char(C) ( ((C) >= 'a' && (C) <= 'z') || ((C) >= 'A' && \
2015-04-24 17:03:44 +01:00
(C) <= 'Z') || (C) == '_' )
2015-04-13 13:28:17 +01:00
#if __ANDROID__
AAssetManager * Yap_assetManager;
void *
Yap_openAssetFile( const char *path ) {
const char * p = path+8;
AAsset* asset = AAssetManager_open(Yap_assetManager, p, AASSET_MODE_UNKNOWN);
return asset;
}
bool
Yap_isAsset( const char *path )
{
if (Yap_assetManager == NULL)
return false;
2015-04-13 13:28:17 +01:00
return path[0] == '/'&&
2015-04-24 17:03:44 +01:00
path[1] == 'a'&&
path[2] == 's'&&
path[3] == 's'&&
path[4] == 'e'&&
path[5] == 't'&&
path[6] == 's'&&
(path[7] == '/' || path[7] == '\0');
2015-04-13 13:28:17 +01:00
}
bool
Yap_AccessAsset( const char *name, int mode )
{
2015-04-24 17:03:44 +01:00
AAssetManager* mgr = Yap_assetManager;
const char *bufp=name+7;
2015-07-06 12:03:16 +01:00
2015-04-24 17:03:44 +01:00
if (bufp[0] == '/')
bufp++;
if ((mode & W_OK) == W_OK) {
return false;
}
// directory works if file exists
AAssetDir *assetDir = AAssetManager_openDir(mgr, bufp);
if (assetDir) {
AAssetDir_close(assetDir);
return true;
}
return false;
2015-04-13 13:28:17 +01:00
}
bool
Yap_AssetIsFile( const char *name )
{
2015-04-24 17:03:44 +01:00
AAssetManager* mgr = Yap_assetManager;
const char *bufp=name+7;
if (bufp[0] == '/')
2015-04-13 13:28:17 +01:00
bufp++;
2015-04-24 17:03:44 +01:00
// check if file is a directory.
AAsset *asset = AAssetManager_open(mgr, bufp, AASSET_MODE_UNKNOWN);
if (!asset)
return false;
AAsset_close(asset);
return true;
2015-04-13 13:28:17 +01:00
}
bool
Yap_AssetIsDir( const char *name )
{
2015-04-24 17:03:44 +01:00
AAssetManager* mgr = Yap_assetManager;
const char *bufp=name+7;
if (bufp[0] == '/')
2015-04-13 13:28:17 +01:00
bufp++;
2015-04-24 17:03:44 +01:00
// check if file is a directory.
AAssetDir *assetDir = AAssetManager_openDir(mgr, bufp);
if (!assetDir) {
return false;
}
AAssetDir_close(assetDir);
AAsset *asset = AAssetManager_open(mgr, bufp, AASSET_MODE_UNKNOWN);
if (!asset)
return true;
AAsset_close(asset);
return false;
2015-04-13 13:28:17 +01:00
}
int64_t
Yap_AssetSize( const char *name )
{
2015-04-24 17:03:44 +01:00
AAssetManager* mgr = Yap_assetManager;
const char *bufp=name+7;
if (bufp[0] == '/')
2015-04-13 13:28:17 +01:00
bufp++;
2015-04-24 17:03:44 +01:00
AAsset *asset = AAssetManager_open(mgr, bufp, AASSET_MODE_UNKNOWN);
if (!asset)
2015-04-13 13:28:17 +01:00
return -1;
off64_t len = AAsset_getLength64(asset);
2015-04-24 17:03:44 +01:00
AAsset_close(asset);
2015-04-13 13:28:17 +01:00
return len;
}
#endif
/// is_directory: verifies whether an expanded file name
/// points at a readable directory
static bool
2014-11-09 12:06:40 +00:00
is_directory(const char *FileName)
{
2015-04-13 13:28:17 +01:00
#ifdef __ANDROID__
if (Yap_isAsset(FileName)) {
2015-04-24 17:03:44 +01:00
return Yap_AssetIsDir(FileName);
}
2015-04-13 13:28:17 +01:00
#endif
2014-11-09 12:06:40 +00:00
#ifdef __WINDOWS__
DWORD dwAtts = GetFileAttributes( FileName );
2015-04-24 17:03:44 +01:00
if (dwAtts == INVALID_FILE_ATTRIBUTES)
return false;
return (dwAtts & FILE_ATTRIBUTE_DIRECTORY);
#elif HAVE_LSTAT
2015-04-24 17:03:44 +01:00
struct stat buf;
if (lstat(FileName, &buf) == -1) {
/* return an error number */
return false;
}
return S_ISDIR(buf.st_mode);
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-24 17:03:44 +01:00
"stat not available in this configuration");
return false;
#endif
}
2014-11-09 12:06:40 +00:00
/// has_access just calls access
/// it uses F_OK, R_OK and friend
static bool
has_access(const char *FileName, int mode)
{
2015-04-13 13:28:17 +01:00
#ifdef __ANDROID__
if (Yap_isAsset(FileName)) {
2015-04-24 17:03:44 +01:00
return Yap_AccessAsset(FileName, mode);
}
2015-04-13 13:28:17 +01:00
#endif
#if HAVE_ACCESS
if (access( FileName, mode ) == 0)
return true;
if (errno == EINVAL) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
"bad flags to access");
}
return false;
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-13 13:28:17 +01:00
"access not available in this configuration");
return false;
#endif
}
static bool
exists( const char *f)
{
return has_access( f, F_OK );
}
static int
2015-04-24 17:03:44 +01:00
dir_separator (int ch)
{
#ifdef MAC
return (ch == ':');
#elif ATARI || _MSC_VER
return (ch == '\\');
#elif defined(__MINGW32__) || defined(__CYGWIN__)
return (ch == '\\' || ch == '/');
#else
return (ch == '/');
#endif
}
int
Yap_dir_separator (int ch)
{
return dir_separator (ch);
}
2014-11-09 12:06:40 +00:00
#if __WINDOWS__
2014-11-28 02:30:58 +00:00
#include <psapi.h>
2014-11-09 12:06:40 +00:00
2014-11-28 02:30:58 +00:00
char *libdir = NULL;
#endif
2014-11-09 12:06:40 +00:00
2015-06-17 23:49:02 +01:00
bool
Yap_IsAbsolutePath(const char *p0)
{
2015-06-17 23:49:02 +01:00
// verify first if expansion is needed: ~/ or $HOME/
char c[MAXPATHLEN+1];
char *p = expandVars( p0, c, MAXPATHLEN );
#if _WIN32 || __MINGW32__
return !PathIsRelative(p);
#else
return p[0] == '/';
#endif
}
2015-04-13 13:28:17 +01:00
#define isValidEnvChar(C) ( ((C) >= 'a' && (C) <= 'z') || ((C) >= 'A' && \
2015-04-24 17:03:44 +01:00
(C) <= 'Z') || (C) == '_' )
2015-04-13 13:28:17 +01:00
// this is necessary because
// support for ~expansion at the beginning
// systems like Android do not do this.
static char *
yapExpandVars (const char *source, char *result)
{
const char *src = source;
char *res = result;
2015-06-17 23:49:02 +01:00
2015-04-24 17:03:44 +01:00
if(result == NULL)
result = malloc( YAP_FILENAME_MAX+1);
2015-04-13 13:28:17 +01:00
if (strlen(source) >= YAP_FILENAME_MAX) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "%s in true_file-name is larger than the buffer size (%d bytes)", source, strlen(source));
2015-04-13 13:28:17 +01:00
}
/* step 1: eating home information */
if (source[0] == '~') {
if (dir_separator(source[1]) || source[1] == '\0')
{
char *s;
src++;
#if defined(_WIN32)
s = getenv("HOMEDRIVE");
if (s != NULL)
strncpy (result, getenv ("HOMEDRIVE"), YAP_FILENAME_MAX);
2015-04-24 17:03:44 +01:00
//s = getenv("HOMEPATH");
2015-04-13 13:28:17 +01:00
#else
s = getenv ("HOME");
2015-04-24 17:03:44 +01:00
#endif
2015-04-13 13:28:17 +01:00
if (s != NULL)
strncpy (result, s, YAP_FILENAME_MAX);
2015-04-24 17:03:44 +01:00
strcat(result,src);
return result;
2015-04-13 13:28:17 +01:00
} else {
#if HAVE_GETPWNAM
struct passwd *user_passwd;
src++;
while (!dir_separator((*res = *src)) && *res != '\0')
2015-04-24 17:03:44 +01:00
res++, src++;
res[0] = '\0';
2015-04-13 13:28:17 +01:00
if ((user_passwd = getpwnam (result)) == NULL) {
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, MkAtomTerm(Yap_LookupAtom(source)),"User %s does not exist in %s", result, source);
2015-04-13 13:28:17 +01:00
return NULL;
}
strncpy (result, user_passwd->pw_dir, YAP_FILENAME_MAX);
2015-04-24 17:03:44 +01:00
strcat(result, src);
2015-04-13 13:28:17 +01:00
#else
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, MkAtomTerm(Yap_LookupAtom(source)),"User %s cannot be found in %s, missing getpwnam", result, source);
2015-04-13 13:28:17 +01:00
return NULL;
#endif
}
return result;
}
// do VARIABLE expansion
else if (source[0] == '$') {
/* follow SICStus expansion rules */
2015-04-24 17:03:44 +01:00
char v[YAP_FILENAME_MAX+1];
int ch;
2015-04-13 13:28:17 +01:00
char *s;
src = source+1;
if (src[0] == '{') {
2015-04-24 17:03:44 +01:00
res = v;
2015-04-13 13:28:17 +01:00
src++;
2015-04-24 17:03:44 +01:00
while ((*res = (ch = *src++)) && isValidEnvChar (ch) && ch != '}') {
res++;
2015-04-13 13:28:17 +01:00
}
if (ch == '}') {
2015-04-24 17:03:44 +01:00
// {...}
// done
res[0] = '\0';
2015-04-13 13:28:17 +01:00
}
2015-04-24 17:03:44 +01:00
} else {
res = v;
while ((*res = (ch = *src++)) && isValidEnvChar (ch) && ch != '}') {
res++;
2015-04-13 13:28:17 +01:00
}
src--;
res[0] = '\0';
}
2015-04-24 17:03:44 +01:00
if ((s = (char *) getenv (v))) {
strcpy (result, s);
strcat (result, src);
} else
strcpy( result, src);
2015-04-13 13:28:17 +01:00
}
else {
strncpy (result, source, YAP_FILENAME_MAX);
}
return result;
}
2015-06-17 23:49:02 +01:00
static char *
expandVars(const char *pattern, char *expanded, int maxlen)
{
2015-04-13 13:28:17 +01:00
2015-04-24 17:03:44 +01:00
return yapExpandVars(pattern, expanded);
2015-04-15 15:07:04 +01:00
#if ( __WIN32 || __MINGW32__ ) && defined(ENABLE_SYSTEM_EXPANSION)
DWORD retval=0;
2015-06-17 23:49:02 +01:00
// notice that the file does not need to exist
2015-04-13 13:28:17 +01:00
if (ini == NULL) {
ini = malloc(strlen(w)+1);
}
retval = ExpandEnvironmentStrings(pattern,
expanded,
maxlen);
2015-04-13 13:28:17 +01:00
if (retval == 0)
{
Yap_WinError("Generating a full path name for a file" );
return NULL;
}
2015-04-13 13:28:17 +01:00
return expanded;
2015-04-15 15:07:04 +01:00
#elif HAVE_WORDEXP && defined(ENABLE_SYSTEM_EXPANSION)
2015-04-13 13:28:17 +01:00
wordexp_t result;
/* Expand the string for the program to run. */
switch (wordexp (pattern, &result, 0))
{
case 0: /* Successful. */
if (result.we_wordv[1]) {
wordfree (&result);
return NULL;
} else {
char *w = result.we_wordv[0];
2015-04-24 17:03:44 +01:00
if (expanded == NULL) {
expanded = malloc(strlen(w)+1);
}
strncpy( expanded, w, maxlen );
wordfree (&result);
return expanded;
}
break;
case WRDE_NOSPACE:
/* If the error was WRDE_NOSPACE,
then perhaps part of the result was allocated. */
wordfree (&result);
default: /* Some other error. */
return NULL;
}
2015-04-13 13:28:17 +01:00
#else
// just use basic
if (expanded == NULL) {
expanded = malloc(strlen(pattern)+1);
}
strcpy(expanded, pattern);
#endif
2015-04-13 13:28:17 +01:00
return expanded;
}
#if _WIN32 || defined(__MINGW32__)
// straightforward conversion from Unix style to WIN style
// check cygwin path.cc for possible improvements
static char *
unix2win( const char *source, char *target, int max)
{
char *s = target;
const char *s0 = source;
char *s1;
int ch;
if (s == NULL)
s = malloc(YAP_FILENAME_MAX+1);
s1 = s;
// win32 syntax
// handle drive notation, eg //a/
if (s0[0] == '\0') {
s[0] = '.';
s[1] = '\0';
return s;
}
if (s0[0] == '/' && s0[1] == '/' && isalpha(s0[2]) && s0[3] == '/')
2015-04-24 17:03:44 +01:00
{
s1[0] = s0[2];
s1[1] = ':';
s1[2] = '\\';
s0+=4;
s1+=3;
}
while ((ch = *s1++ = *s0++)) {
if (ch == '$') {
s1[-1] = '%';
ch = *s0;
// handle $(....)
if (ch == '{') {
s0++;
while ((ch = *s0++) != '}') {
*s1++ = ch;
if (ch == '\0') return FALSE;
}
*s1++ = '%';
} else {
while (((ch = *s1++ = *s0++) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch == '-') || (ch >= '0' && ch <= '9') || (ch == '_'));
s1[-1] = '%';
*s1++ = ch;
if (ch == '\0') { s1--; s0--; }
}
} else if (ch == '/')
s1[-1] = '\\';
}
return s;
}
#endif
2015-06-17 23:49:02 +01:00
static char *
OsPath(const char *p, char *buf)
2015-04-13 13:28:17 +01:00
{
2015-07-06 12:03:16 +01:00
return (char *)p;
}
2015-07-06 12:03:16 +01:00
2015-06-17 23:49:02 +01:00
static char *
2015-07-06 12:03:16 +01:00
PrologPath(const char *Y, char *X) {
2015-04-24 17:03:44 +01:00
return (char *)Y ;
}
2015-07-06 12:03:16 +01:00
#if _WIN32
#define HAVE_BASENAME 1
#define HAVE_REALPATH 1
#define HAVE_WORDEXP 1
#endif
2015-06-17 23:49:02 +01:00
static bool ChDir(const char *path) {
bool rc = false;
2015-06-17 23:49:02 +01:00
char *qpath = Yap_AbsoluteFile(path, NULL);
2015-04-13 13:28:17 +01:00
#ifdef __ANDROID__
if (GLOBAL_AssetsWD) {
free( GLOBAL_AssetsWD );
GLOBAL_AssetsWD = NULL;
}
if (Yap_isAsset(qpath) ) {
AAssetManager* mgr = Yap_assetManager;
const char *ptr = qpath+8;
AAssetDir* d;
if (ptr[0] == '/')
ptr++;
d = AAssetManager_openDir(mgr, ptr);
if (d) {
GLOBAL_AssetsWD = malloc( strlen(qpath) + 1 );
strcpy( GLOBAL_AssetsWD, qpath );
AAssetDir_close( d );
return true;
}
return false;
} else {
GLOBAL_AssetsWD = NULL;
}
#endif
#if _WIN32 || defined(__MINGW32__)
2015-07-06 12:03:16 +01:00
if ((rc = (SetCurrentDirectory(qpath) != 0)) == 0)
2015-04-24 17:03:44 +01:00
{
Yap_WinError("SetCurrentDirectory failed" );
}
#else
rc = (chdir(qpath) == 0);
#endif
free( qpath );
return rc;
}
#if _WIN32 || defined(__MINGW32__)
char *
BaseName(const char *X) {
2015-04-13 13:28:17 +01:00
char *qpath = unix2win(X, NULL, YAP_FILENAME_MAX);
char base[YAP_FILENAME_MAX], ext[YAP_FILENAME_MAX];
_splitpath(qpath, NULL, NULL, base, ext);
strcpy(qpath, base);
strcat(qpath, ext);
return qpath;
}
char *
DirName(const char *X) {
2015-04-13 13:28:17 +01:00
char dir[YAP_FILENAME_MAX];
char drive[YAP_FILENAME_MAX];
char *o = unix2win(X, NULL, YAP_FILENAME_MAX);
int err;
2015-04-13 13:28:17 +01:00
if (!o)
return NULL;
if (( err = _splitpath_s(o, drive, YAP_FILENAME_MAX-1, dir, YAP_FILENAME_MAX-1,NULL, 0, NULL, 0) ) != 0) {
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "could not perform _splitpath %s: %s", X, strerror(errno));
2015-04-13 13:28:17 +01:00
return NULL;
}
strncpy(o, drive, YAP_FILENAME_MAX-1);
strncat(o, dir, YAP_FILENAME_MAX-1);
return o;
}
#endif
static char *myrealpath( const char *path, char *out)
{
#if _WIN32 || defined(__MINGW32__)
DWORD retval=0;
2015-06-17 23:49:02 +01:00
// notice that the file does not need to exist
retval = GetFullPathName(path,
YAP_FILENAME_MAX,
out,
NULL);
2015-04-13 13:28:17 +01:00
if (retval == 0)
{
Yap_WinError("Generating a full path name for a file" );
return NULL;
}
return out;
#elif HAVE_REALPATH
{
char *rc = realpath(path,out);
char *s0;
2015-04-13 13:28:17 +01:00
if (rc == NULL && (errno == ENOENT|| errno == EACCES)) {
char *s = basename((char *)path);
s0 = malloc(strlen(s)+1);
strcpy(s0, s);
if ((rc = myrealpath(dirname((char *)path), out))==NULL) {
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "could not find file %s: %s", path, strerror(errno));
2015-04-13 13:28:17 +01:00
return NULL;
}
if(rc[strlen(rc)-1] != '/' )
strcat(rc, "/");
strcat(rc, s0);
free(s0);
}
2015-04-24 17:03:44 +01:00
return rc;
}
#else
return NULL;
2015-04-13 13:28:17 +01:00
#endif
}
char *
2015-06-17 23:49:02 +01:00
Yap_AbsoluteFile(const char *spec, char *tmp)
{
2015-07-06 12:03:16 +01:00
char *rc;
2015-04-13 13:28:17 +01:00
char o[YAP_FILENAME_MAX+1];
2015-04-24 17:03:44 +01:00
#if _WIN32 || defined(__MINGW32__)
2015-04-13 13:28:17 +01:00
char u[YAP_FILENAME_MAX+1];
// first pass, remove Unix style stuff
if (unix2win(spec, u, YAP_FILENAME_MAX) == NULL)
return NULL;
spec = (const char *)u;
#endif
if (tmp == NULL) {
tmp = malloc(YAP_FILENAME_MAX+1);
if (tmp == NULL) {
return NULL;
}
}
2015-06-17 23:49:02 +01:00
if ( 1 || trueGlobalPrologFlag(FILE_NAME_VARIABLES_FLAG) )
{
2015-04-13 13:28:17 +01:00
spec=expandVars(spec,o,YAP_FILENAME_MAX);
}
2015-04-13 13:28:17 +01:00
#if HAVE_REALPATH
rc = myrealpath(spec, tmp);
#endif
return rc;
}
2015-06-17 23:49:02 +01:00
/*
static char *canoniseFileName( char *path) {
#if HAVE_REALPATH && HAVE_BASENAME
2015-04-13 13:28:17 +01:00
#if _WIN32 || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
char *o = malloc(YAP_FILENAME_MAX+1);
if (!o)
return NULL;
// first pass, remove Unix style stuff
if (unix2win(path, o, YAP_FILENAME_MAX) == NULL)
return NULL;
path = o;
2015-04-13 13:28:17 +01:00
#endif
char *rc, *tmp = malloc(PATH_MAX);
if (tmp == NULL) return NULL;
rc = myrealpath(path, tmp);
if (rc != tmp)
free(tmp);
#if _WIN32 || defined(__MINGW32__)
free(o);
#endif
return rc;
#endif
}
2015-06-17 23:49:02 +01:00
*/
2015-06-17 23:49:02 +01:00
static Int
absolute_file_name( USES_REGS1 )
{
Term t = Deref(ARG1);
const char *fp;
bool rc;
char s[MAXPATHLEN+1];
2015-07-06 12:03:16 +01:00
2015-06-17 23:49:02 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "absolute_file_name");
return false;
} else if (!IsAtomTerm(t)) {
Yap_Error(TYPE_ERROR_ATOM, t, "absolute_file_name");
return false;
}
if (!(fp = Yap_AbsoluteFile( RepAtom(AtomOfTerm(t))->StrOfAE, s)))
return false;
rc = Yap_unify(MkAtomTerm(Yap_LookupAtom(fp)), ARG2);
if (fp != s)
free( (void *)fp );
return rc;
}
static Int
prolog_to_os_filename( USES_REGS1 )
{
2015-07-06 12:03:16 +01:00
Term t = Deref(ARG1), t2 = Deref(ARG2);
char *fp;
2015-06-17 23:49:02 +01:00
char out[MAXPATHLEN+1];
2015-07-06 12:03:16 +01:00
if (IsVarTerm(t)) {
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t, "prolog_to_os_filename");
return false;
} else if ( IsAtomTerm(t2) ) {
if (!(fp = PrologPath( RepAtom(AtomOfTerm(t2))->StrOfAE, out)))
return false;
return Yap_unify(ARG1, MkAtomTerm(Yap_LookupAtom( fp )));
} else {
Yap_Error(TYPE_ERROR_ATOM, t2, "prolog_to_os_filename");
return false;
}
2015-06-17 23:49:02 +01:00
} else if (!IsAtomTerm(t)) {
2015-07-06 12:03:16 +01:00
Yap_Error(TYPE_ERROR_ATOM, t, "prolog_to_os_filename");
2015-06-17 23:49:02 +01:00
return false;
}
2015-07-06 12:03:16 +01:00
if (!(fp = OsPath( RepAtom(AtomOfTerm(t))->StrOfAE, out)))
2015-06-17 23:49:02 +01:00
return false;
return Yap_unify(MkAtomTerm(Yap_LookupAtom(fp)), ARG2);
}
Atom Yap_TemporaryFile( const char *prefix, int *fd) {
#if HAVE_MKSTEMP
char *tmp = malloc(PATH_MAX);
int n;
int f;
2015-06-17 23:49:02 +01:00
if (tmp == NULL) return NIL;
strncpy(tmp, prefix, PATH_MAX-1);
n = strlen( tmp );
if (n >= 6 &&
tmp[n-1] == 'X' &&
tmp[n-2] == 'X' &&
tmp[n-3] == 'X' &&
tmp[n-4] == 'X' &&
tmp[n-5] == 'X' &&
tmp[n-6] == 'X')
f = mkstemp(tmp);
else {
strncat(tmp, "XXXXXX", PATH_MAX-1);
f = mkstemp(tmp);
}
if (fd) *fd = f;
2015-06-17 23:49:02 +01:00
return Yap_LookupAtom(tmp);
#else
2015-06-17 23:49:02 +01:00
return AtomNil;
#endif
}
2015-07-06 12:03:16 +01:00
/** @pred make_directory(+ _Dir_)
Create a directory _Dir_. The name of the directory must be an atom.
*/
static Int
make_directory( USES_REGS1 )
{
const char *fd = AtomName(AtomOfTerm(ARG1));
#if defined(__MINGW32__) || _MSC_VER
if (_mkdir(fd) == -1) {
#else
if (mkdir(fd, 0777) == -1) {
#endif
/* return an error number */
return false; // errno?
}
return true;
}
static Int
p_rmdir( USES_REGS1 )
{
const char *fd = AtomName(AtomOfTerm(ARG1));
#if defined(__MINGW32__) || _MSC_VER
if (_rmdir(fd) == -1) {
#else
if (rmdir(fd) == -1) {
#endif
/* return an error number */
return(Yap_unify(ARG2, MkIntTerm(errno)));
}
return true;
}
static bool
2014-11-28 03:21:32 +00:00
initSysPath(Term tlib, Term tcommons, bool dir_done, bool commons_done) {
2014-11-28 02:30:58 +00:00
CACHE_REGS
int len;
2014-11-09 12:06:40 +00:00
2015-02-16 11:43:42 +00:00
#if __WINDOWS__
{
char *dir;
if ((dir = Yap_RegistryGetString("library")) &&
is_directory(dir)) {
if (! Yap_unify( tlib,
MkAtomTerm(Yap_LookupAtom(dir))) )
return FALSE;
}
dir_done = true;
if ((dir = Yap_RegistryGetString("prolog_commons")) &&
is_directory(dir)) {
if (! Yap_unify( tcommons,
MkAtomTerm(Yap_LookupAtom(dir))) )
return FALSE;
}
commons_done = true;
}
if (dir_done && commons_done)
return TRUE;
#endif
2014-11-28 02:30:58 +00:00
strncpy(LOCAL_FileNameBuf, YAP_SHAREDIR, YAP_FILENAME_MAX);
strncat(LOCAL_FileNameBuf,"/", YAP_FILENAME_MAX);
len = strlen(LOCAL_FileNameBuf);
if (!dir_done) {
strncat(LOCAL_FileNameBuf, "Yap", YAP_FILENAME_MAX);
2015-01-20 03:00:42 +00:00
if (is_directory(LOCAL_FileNameBuf))
2014-11-28 02:30:58 +00:00
{
if (! Yap_unify( tlib,
MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf))) )
return FALSE;
2015-06-17 23:49:02 +01:00
dir_done = true;
2014-11-28 02:30:58 +00:00
}
}
if (!commons_done) {
LOCAL_FileNameBuf[len] = '\0';
strncat(LOCAL_FileNameBuf, "PrologCommons", YAP_FILENAME_MAX);
if (is_directory(LOCAL_FileNameBuf)) {
if (! Yap_unify( tcommons,
MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf))) )
return FALSE;
}
2014-11-28 03:21:32 +00:00
commons_done = true;
2014-11-28 02:30:58 +00:00
}
if (dir_done && commons_done)
return TRUE;
2014-11-28 02:30:58 +00:00
#if __WINDOWS__
{
size_t buflen;
char *pt;
/* couldn't find it where it was supposed to be,
let's try using the executable */
if (!GetModuleFileName( NULL, LOCAL_FileNameBuf, YAP_FILENAME_MAX)) {
2015-01-20 03:00:42 +00:00
Yap_WinError( "could not find executable name" );
2014-11-28 02:30:58 +00:00
/* do nothing */
return FALSE;
}
buflen = strlen(LOCAL_FileNameBuf);
pt = LOCAL_FileNameBuf+buflen;
while (*--pt != '\\') {
/* skip executable */
if (pt == LOCAL_FileNameBuf) {
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "could not find executable name");
2014-11-28 02:30:58 +00:00
/* do nothing */
return FALSE;
}
}
while (*--pt != '\\') {
/* skip parent directory "bin\\" */
if (pt == LOCAL_FileNameBuf) {
2015-09-25 10:57:26 +01:00
Yap_FileError(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "could not find executable name");
2014-11-28 02:30:58 +00:00
/* do nothing */
return FALSE;
}
}
/* now, this is a possible location for the ROOT_DIR, let's look for a share directory here */
pt[1] = '\0';
/* grosse */
strncat(LOCAL_FileNameBuf,"lib\\Yap",YAP_FILENAME_MAX);
libdir = Yap_AllocCodeSpace(strlen(LOCAL_FileNameBuf)+1);
strncpy(libdir, LOCAL_FileNameBuf, strlen(LOCAL_FileNameBuf)+1);
pt[1] = '\0';
strncat(LOCAL_FileNameBuf,"share",YAP_FILENAME_MAX);
}
strncat(LOCAL_FileNameBuf,"\\", YAP_FILENAME_MAX);
len = strlen(LOCAL_FileNameBuf);
strncat(LOCAL_FileNameBuf, "Yap", YAP_FILENAME_MAX);
if (!dir_done && is_directory(LOCAL_FileNameBuf)) {
if (! Yap_unify( tlib,
MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf))) )
return FALSE;
}
2014-11-28 03:21:32 +00:00
dir_done = true;
2014-11-28 02:30:58 +00:00
LOCAL_FileNameBuf[len] = '\0';
strncat(LOCAL_FileNameBuf, "PrologCommons", YAP_FILENAME_MAX);
if (!commons_done && is_directory(LOCAL_FileNameBuf)) {
if (! Yap_unify( tcommons,
MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf))) )
2014-11-09 12:06:40 +00:00
return FALSE;
2014-03-04 12:02:26 +00:00
}
2014-11-28 03:21:32 +00:00
commons_done = true;
2014-11-28 02:30:58 +00:00
#endif
return dir_done && commons_done;
}
2014-11-28 02:30:58 +00:00
2014-11-05 07:45:36 +00:00
static Int
2015-06-17 23:49:02 +01:00
libraries_directories( USES_REGS1 )
2014-11-09 12:06:40 +00:00
{
2014-11-28 03:21:32 +00:00
return initSysPath( ARG1, ARG2 , false, false );
2014-11-09 12:06:40 +00:00
}
2014-11-28 02:30:58 +00:00
2014-11-09 12:06:40 +00:00
static Int
2015-06-17 23:49:02 +01:00
system_library( USES_REGS1 )
2014-11-09 12:06:40 +00:00
{
2014-11-28 03:21:32 +00:00
return initSysPath( ARG1, MkVarTerm(), false, true );
2014-11-05 07:45:36 +00:00
}
static Int
2015-06-17 23:49:02 +01:00
commons_library( USES_REGS1 )
2014-11-05 07:45:36 +00:00
{
2014-11-28 03:21:32 +00:00
return initSysPath( MkVarTerm(), ARG1, true, false );
}
static Int
p_dir_sp ( USES_REGS1 )
{
#ifdef MAC
Term t = MkIntTerm(':');
2011-03-22 11:07:17 +00:00
Term t2 = MkIntTerm('/');
#elif ATARI || _MSC_VER || defined(__MINGW32__)
Term t = MkIntTerm('\\');
2011-03-22 11:07:17 +00:00
Term t2 = MkIntTerm('/');
#else
Term t = MkIntTerm('/');
2011-03-22 11:07:17 +00:00
Term t2 = MkIntTerm('/');
#endif
2011-03-22 11:07:17 +00:00
return Yap_unify_constant(ARG1,t) || Yap_unify_constant(ARG1,t2) ;
}
void
Yap_InitPageSize(void)
{
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
Yap_page_size = si.dwPageSize;
#elif HAVE_UNISTD_H
#if defined(__FreeBSD__) || defined(__DragonFly__)
Yap_page_size = getpagesize();
#elif defined(_AIX)
Yap_page_size = sysconf(_SC_PAGE_SIZE);
#elif !defined(_SC_PAGESIZE)
Yap_page_size = getpagesize();
#else
Yap_page_size = sysconf(_SC_PAGESIZE);
#endif
#else
2015-04-24 17:03:44 +01:00
bla bla
#endif
2015-04-24 17:03:44 +01:00
}
#ifdef SIMICS
#ifdef HAVE_GETRUSAGE
#undef HAVE_GETRUSAGE
#endif
#ifdef HAVE_TIMES
#undef HAVE_TIMES
#endif
#endif /* SIMICS */
#ifdef _WIN32
#if HAVE_GETRUSAGE
#undef HAVE_GETRUSAGE
#endif
#endif
#if HAVE_GETRUSAGE
#if HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#if THREADS
#define StartOfTimes (*(LOCAL_ThreadHandle.start_of_timesp))
#define last_time (*(LOCAL_ThreadHandle.last_timep))
#define StartOfTimes_sys (*(LOCAL_ThreadHandle.start_of_times_sysp))
#define last_time_sys (*(LOCAL_ThreadHandle.last_time_sysp))
#else
/* since the point YAP was started */
static struct timeval StartOfTimes;
/* since last call to runtime */
static struct timeval last_time;
/* same for system time */
static struct timeval last_time_sys;
static struct timeval StartOfTimes_sys;
#endif
/* store user time in this variable */
static void
InitTime (int wid)
{
struct rusage rusage;
#if THREADS
REMOTE_ThreadHandle(wid).start_of_timesp = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).last_timep = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).start_of_times_sysp = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).last_time_sysp = (struct timeval *)malloc(sizeof(struct timeval));
getrusage(RUSAGE_SELF, &rusage);
(*REMOTE_ThreadHandle(wid).last_timep).tv_sec =
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_timesp).tv_sec =
rusage.ru_utime.tv_sec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_usec =
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_timesp).tv_usec =
rusage.ru_utime.tv_usec;
(*REMOTE_ThreadHandle(wid).last_time_sysp).tv_sec =
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).tv_sec =
rusage.ru_stime.tv_sec;
(*REMOTE_ThreadHandle(wid).last_time_sysp).tv_usec =
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).tv_usec =
rusage.ru_stime.tv_usec;
#else
getrusage(RUSAGE_SELF, &rusage);
last_time.tv_sec =
2015-01-20 03:00:42 +00:00
StartOfTimes.tv_sec =
rusage.ru_utime.tv_sec;
last_time.tv_usec =
2015-01-20 03:00:42 +00:00
StartOfTimes.tv_usec =
rusage.ru_utime.tv_usec;
last_time_sys.tv_sec =
2015-01-20 03:00:42 +00:00
StartOfTimes_sys.tv_sec =
rusage.ru_stime.tv_sec;
last_time_sys.tv_usec =
2015-01-20 03:00:42 +00:00
StartOfTimes_sys.tv_usec =
rusage.ru_stime.tv_usec;
#endif
}
UInt
Yap_cputime ( void )
{
CACHE_REGS
2015-04-24 17:03:44 +01:00
struct rusage rusage;
2015-04-24 17:03:44 +01:00
getrusage(RUSAGE_SELF, &rusage);
return((rusage.ru_utime.tv_sec - StartOfTimes.tv_sec)) * 1000 +
((rusage.ru_utime.tv_usec - StartOfTimes.tv_usec) / 1000);
}
void Yap_cputime_interval(Int *now,Int *interval)
{
CACHE_REGS
2015-04-24 17:03:44 +01:00
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
*now = (rusage.ru_utime.tv_sec - StartOfTimes.tv_sec) * 1000 +
(rusage.ru_utime.tv_usec - StartOfTimes.tv_usec) / 1000;
*interval = (rusage.ru_utime.tv_sec - last_time.tv_sec) * 1000 +
(rusage.ru_utime.tv_usec - last_time.tv_usec) / 1000;
last_time.tv_usec = rusage.ru_utime.tv_usec;
last_time.tv_sec = rusage.ru_utime.tv_sec;
}
void Yap_systime_interval(Int *now,Int *interval)
{
CACHE_REGS
2015-04-24 17:03:44 +01:00
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
*now = (rusage.ru_stime.tv_sec - StartOfTimes_sys.tv_sec) * 1000 +
(rusage.ru_stime.tv_usec - StartOfTimes_sys.tv_usec) / 1000;
*interval = (rusage.ru_stime.tv_sec - last_time_sys.tv_sec) * 1000 +
(rusage.ru_stime.tv_usec - last_time_sys.tv_usec) / 1000;
last_time_sys.tv_usec = rusage.ru_stime.tv_usec;
last_time_sys.tv_sec = rusage.ru_stime.tv_sec;
}
#elif defined(_WIN32)
#ifdef __GNUC__
/* This is stolen from the Linux kernel.
The problem is that mingw32 does not seem to have acces to div */
#ifndef do_div
2015-04-24 17:03:44 +01:00
#define do_div(n,base) ({ \
unsigned long __upper, __low, __high, __mod; \
asm("":"=a" (__low), "=d" (__high):"A" (n)); \
__upper = __high; \
if (__high) { \
__upper = __high % (base); \
__high = __high / (base); \
} \
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (base), "0" (__low), "1" (__upper)); \
asm("":"=A" (n):"a" (__low),"d" (__high)); \
__mod; \
})
#endif
#endif
#include <time.h>
2015-04-24 17:03:44 +01:00
static FILETIME StartOfTimes, last_time;
static FILETIME StartOfTimes_sys, last_time_sys;
static clock_t TimesStartOfTimes, Times_last_time;
/* store user time in this variable */
static void
2012-12-19 00:48:43 +00:00
InitTime (int wid)
{
HANDLE hProcess = GetCurrentProcess();
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
if (!GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime)) {
/* WIN98 */
clock_t t;
t = clock ();
Times_last_time = TimesStartOfTimes = t;
} else {
2012-12-19 00:48:43 +00:00
#if THREADS
2012-12-20 21:13:20 +00:00
REMOTE_ThreadHandle(wid).start_of_timesp = (struct _FILETIME *)malloc(sizeof(FILETIME));
REMOTE_ThreadHandle(wid).last_timep = (struct _FILETIME *)malloc(sizeof(FILETIME));
REMOTE_ThreadHandle(wid).start_of_times_sysp = (struct _FILETIME *)malloc(sizeof(FILETIME));
REMOTE_ThreadHandle(wid).last_time_sysp = (struct _FILETIME *)malloc(sizeof(FILETIME));
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).last_timep).dwLowDateTime =
2012-12-20 21:13:20 +00:00
UserTime.dwLowDateTime;
(*REMOTE_ThreadHandle(wid).last_timep).dwHighDateTime =
UserTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).start_of_timesp).dwLowDateTime =
UserTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_timesp).dwHighDateTime =
UserTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).last_time_sysp).dwLowDateTime =
KernelTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).last_time_sysp).dwHighDateTime =
KernelTime.dwHighDateTime;
2012-12-19 00:48:43 +00:00
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).dwLowDateTime =
KernelTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).dwHighDateTime =
KernelTime.dwHighDateTime;
2012-12-19 00:48:43 +00:00
#else
2015-01-20 03:00:42 +00:00
last_time.dwLowDateTime =
2012-12-19 00:48:43 +00:00
UserTime.dwLowDateTime;
last_time.dwHighDateTime =
UserTime.dwHighDateTime;
StartOfTimes.dwLowDateTime =
UserTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
StartOfTimes.dwHighDateTime =
2012-12-19 00:48:43 +00:00
UserTime.dwHighDateTime;
last_time_sys.dwLowDateTime =
KernelTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
last_time_sys.dwHighDateTime =
2012-12-19 00:48:43 +00:00
KernelTime.dwHighDateTime;
StartOfTimes_sys.dwLowDateTime =
KernelTime.dwLowDateTime;
2015-01-20 03:00:42 +00:00
StartOfTimes_sys.dwHighDateTime =
2012-12-19 00:48:43 +00:00
KernelTime.dwHighDateTime;
#endif
}
}
#ifdef __GNUC__
2015-01-20 03:00:42 +00:00
static unsigned long long int
sub_utime(FILETIME t1, FILETIME t2)
{
ULARGE_INTEGER u[2];
memcpy((void *)u,(void *)&t1,sizeof(FILETIME));
memcpy((void *)(u+1),(void *)&t2,sizeof(FILETIME));
2015-01-20 03:00:42 +00:00
return
u[0].QuadPart - u[1].QuadPart;
}
#endif
UInt
2012-06-29 21:37:11 +01:00
Yap_cputime ( void )
{
HANDLE hProcess = GetCurrentProcess();
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
if (!GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime)) {
clock_t t;
t = clock ();
return(((t - TimesStartOfTimes)*1000) / CLOCKS_PER_SEC);
} else {
#ifdef __GNUC__
unsigned long long int t =
sub_utime(UserTime,StartOfTimes);
do_div(t,10000);
return((Int)t);
#endif
#ifdef _MSC_VER
__int64 t = *(__int64 *)&UserTime - *(__int64 *)&StartOfTimes;
return((Int)(t/10000));
#endif
}
}
void Yap_cputime_interval(Int *now,Int *interval)
{
HANDLE hProcess = GetCurrentProcess();
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
if (!GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime)) {
clock_t t;
t = clock ();
*now = ((t - TimesStartOfTimes)*1000) / CLOCKS_PER_SEC;
*interval = (t - Times_last_time) * 1000 / CLOCKS_PER_SEC;
Times_last_time = t;
} else {
#ifdef __GNUC__
unsigned long long int t1 =
sub_utime(UserTime, StartOfTimes);
unsigned long long int t2 =
sub_utime(UserTime, last_time);
do_div(t1,10000);
*now = (Int)t1;
do_div(t2,10000);
*interval = (Int)t2;
#endif
#ifdef _MSC_VER
__int64 t1 = *(__int64 *)&UserTime - *(__int64 *)&StartOfTimes;
__int64 t2 = *(__int64 *)&UserTime - *(__int64 *)&last_time;
*now = (Int)(t1/10000);
*interval = (Int)(t2/10000);
#endif
last_time.dwLowDateTime = UserTime.dwLowDateTime;
last_time.dwHighDateTime = UserTime.dwHighDateTime;
}
}
void Yap_systime_interval(Int *now,Int *interval)
{
HANDLE hProcess = GetCurrentProcess();
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
if (!GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime)) {
*now = *interval = 0; /* not available */
} else {
#ifdef __GNUC__
unsigned long long int t1 =
sub_utime(KernelTime, StartOfTimes_sys);
unsigned long long int t2 =
sub_utime(KernelTime, last_time_sys);
do_div(t1,10000);
*now = (Int)t1;
do_div(t2,10000);
*interval = (Int)t2;
#endif
#ifdef _MSC_VER
__int64 t1 = *(__int64 *)&KernelTime - *(__int64 *)&StartOfTimes_sys;
__int64 t2 = *(__int64 *)&KernelTime - *(__int64 *)&last_time_sys;
*now = (Int)(t1/10000);
*interval = (Int)(t2/10000);
#endif
last_time_sys.dwLowDateTime = KernelTime.dwLowDateTime;
last_time_sys.dwHighDateTime = KernelTime.dwHighDateTime;
}
}
#elif HAVE_TIMES
#if defined(_WIN32)
#include <time.h>
#define TicksPerSec CLOCKS_PER_SEC
#else
#if HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
#endif
#if defined(__sun__) && (defined(__svr4__) || defined(__SVR4))
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#define TicksPerSec CLK_TCK
#endif
#if defined(__alpha) || defined(__FreeBSD__) || defined(__linux__) || defined(__DragonFly__)
#if HAVE_TIME_H
#include <time.h>
#endif
#define TicksPerSec sysconf(_SC_CLK_TCK)
#endif
#if !TMS_IN_SYS_TIME
#if HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
#endif
static clock_t StartOfTimes, last_time;
static clock_t StartOfTimes_sys, last_time_sys;
/* store user time in this variable */
static void
InitTime (void)
{
struct tms t;
times (&t);
(*REMOTE_ThreadHandle(wid).last_timep) = StartOfTimes = t.tms_utime;
last_time_sys = StartOfTimes_sys = t.tms_stime;
}
UInt
Yap_cputime (void)
{
struct tms t;
times(&t);
return((t.tms_utime - StartOfTimes)*1000 / TicksPerSec);
}
void Yap_cputime_interval(Int *now,Int *interval)
{
struct tms t;
times (&t);
*now = ((t.tms_utime - StartOfTimes)*1000) / TicksPerSec;
*interval = (t.tms_utime - last_time) * 1000 / TicksPerSec;
last_time = t.tms_utime;
}
void Yap_systime_interval(Int *now,Int *interval)
{
struct tms t;
times (&t);
*now = ((t.tms_stime - StartOfTimes_sys)*1000) / TicksPerSec;
*interval = (t.tms_stime - last_time_sys) * 1000 / TicksPerSec;
last_time_sys = t.tms_stime;
}
#else /* HAVE_TIMES */
#ifdef SIMICS
#include <sys/time.h>
/* since the point YAP was started */
static struct timeval StartOfTimes;
/* since last call to runtime */
static struct timeval last_time;
/* store user time in this variable */
static void
InitTime (int wid)
{
struct timeval tp;
gettimeofday(&tp,NULL);
(*REMOTE_ThreadHandle(wid).last_timep).tv_sec = (*REMOTE_ThreadHandle.start_of_timesp(wid)).tv_sec = tp.tv_sec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_usec = (*REMOTE_ThreadHandle.start_of_timesp(wid)).tv_usec = tp.tv_usec;
}
UInt
Yap_cputime (void)
{
struct timeval tp;
gettimeofday(&tp,NULL);
if (StartOfTimes.tv_usec > tp.tv_usec)
return((tp.tv_sec - StartOfTimes.tv_sec - 1) * 1000 +
(StartOfTimes.tv_usec - tp.tv_usec) /1000);
else
return((tp.tv_sec - StartOfTimes.tv_sec)) * 1000 +
((tp.tv_usec - StartOfTimes.tv_usec) / 1000);
}
void Yap_cputime_interval(Int *now,Int *interval)
{
struct timeval tp;
gettimeofday(&tp,NULL);
*now = (tp.tv_sec - StartOfTimes.tv_sec) * 1000 +
(tp.tv_usec - StartOfTimes.tv_usec) / 1000;
*interval = (tp.tv_sec - last_time.tv_sec) * 1000 +
(tp.tv_usec - last_time.tv_usec) / 1000;
last_time.tv_usec = tp.tv_usec;
last_time.tv_sec = tp.tv_sec;
}
void Yap_systime_interval(Int *now,Int *interval)
{
*now = *interval = 0; /* not available */
}
#endif /* SIMICS */
#ifdef COMMENTED_OUT
/* This code is not working properly. I left it here to help future ports */
#ifdef MPW
#include <files.h>
#include <Events.h>
#define TicksPerSec 60.0
static double
real_cputime ()
{
return (((double) TickCount ()) / TicksPerSec);
}
#endif /* MPW */
#ifdef LATTICE
#include "osbind.h"
static long *ptime;
gettime ()
{
*ptime = *(long *) 0x462;
}
static double
real_cputime ()
{
long thetime;
ptime = &thetime;
xbios (38, gettime);
return (((double) thetime) / (Getrez () == 2 ? 70 : 60));
}
#endif /* LATTICE */
#ifdef M_WILLIAMS
#include <osbind.h>
#include <xbios.h>
static long *ptime;
static long
readtime ()
{
return (*((long *) 0x4ba));
}
static double
real_cputime ()
{
long time;
time = Supexec (readtime);
return (time / 200.0);
}
#endif /* M_WILLIAMS */
#ifdef LIGHT
#undef FALSE
#undef TRUE
#include <FileMgr.h>
#define TicksPerSec 60.0
static double
real_cputime ()
{
return (((double) TickCount ()) / TicksPerSec);
}
#endif /* LIGHT */
#endif /* COMMENTED_OUT */
#endif /* HAVE_GETRUSAGE */
#if HAVE_GETHRTIME
#if HAVE_TIME_H
#include <time.h>
#endif
/* since the point YAP was started */
static hrtime_t StartOfWTimes;
/* since last call to walltime */
2015-06-17 23:49:02 +01:00
#define LastWtime (*(hrtime_t *)ALIGN_BY_TYPE(GLOBAL_LastWtimePtr,hrtime_t))
static void
InitWTime (void)
{
StartOfWTimes = gethrtime();
}
static void
InitLastWtime(void) {
/* ask for twice the space in order to guarantee alignment */
2015-06-17 23:49:02 +01:00
GLOBAL_LastWtimePtr = (void *)Yap_AllocCodeSpace(2*sizeof(hrtime_t));
LastWtime = StartOfWTimes;
}
Int
Yap_walltime (void)
{
hrtime_t tp = gethrtime();
/* return time in milliseconds */
return((Int)((tp-StartOfWTimes)/((hrtime_t)1000000)));
}
void Yap_walltime_interval(Int *now,Int *interval)
{
hrtime_t tp = gethrtime();
/* return time in milliseconds */
*now = (Int)((tp-StartOfWTimes)/((hrtime_t)1000000));
*interval = (Int)((tp-LastWtime)/((hrtime_t)1000000));
LastWtime = tp;
}
#elif HAVE_GETTIMEOFDAY
/* since the point YAP was started */
static struct timeval StartOfWTimes;
/* since last call to walltime */
2015-06-17 23:49:02 +01:00
#define LastWtime (*(struct timeval *)GLOBAL_LastWtimePtr)
/* store user time in this variable */
static void
InitWTime (void)
{
gettimeofday(&StartOfWTimes,NULL);
}
static void
InitLastWtime(void) {
2015-06-17 23:49:02 +01:00
GLOBAL_LastWtimePtr = (void *)Yap_AllocCodeSpace(sizeof(struct timeval));
LastWtime.tv_usec = StartOfWTimes.tv_usec;
LastWtime.tv_sec = StartOfWTimes.tv_sec;
}
Int
Yap_walltime (void)
{
struct timeval tp;
gettimeofday(&tp,NULL);
if (StartOfWTimes.tv_usec > tp.tv_usec)
return((tp.tv_sec - StartOfWTimes.tv_sec - 1) * 1000 +
(StartOfWTimes.tv_usec - tp.tv_usec) /1000);
else
return((tp.tv_sec - StartOfWTimes.tv_sec)) * 1000 +
((tp.tv_usec - LastWtime.tv_usec) / 1000);
}
void Yap_walltime_interval(Int *now,Int *interval)
{
struct timeval tp;
gettimeofday(&tp,NULL);
*now = (tp.tv_sec - StartOfWTimes.tv_sec) * 1000 +
(tp.tv_usec - StartOfWTimes.tv_usec) / 1000;
*interval = (tp.tv_sec - LastWtime.tv_sec) * 1000 +
(tp.tv_usec - LastWtime.tv_usec) / 1000;
LastWtime.tv_usec = tp.tv_usec;
LastWtime.tv_sec = tp.tv_sec;
}
#elif defined(_WIN32)
#include <sys/timeb.h>
#include <time.h>
/* since the point YAP was started */
static struct _timeb StartOfWTimes;
/* since last call to walltime */
2015-06-17 23:49:02 +01:00
#define LastWtime (*(struct timeb *)GLOBAL_LastWtimePtr)
/* store user time in this variable */
static void
InitWTime (void)
{
_ftime(&StartOfWTimes);
}
static void
InitLastWtime(void) {
2015-06-17 23:49:02 +01:00
GLOBAL_LastWtimePtr = (void *)Yap_AllocCodeSpace(sizeof(struct timeb));
LastWtime.time = StartOfWTimes.time;
LastWtime.millitm = StartOfWTimes.millitm;
}
Int
Yap_walltime (void)
{
struct _timeb tp;
_ftime(&tp);
if (StartOfWTimes.millitm > tp.millitm)
return((tp.time - StartOfWTimes.time - 1) * 1000 +
(StartOfWTimes.millitm - tp.millitm));
else
return((tp.time - StartOfWTimes.time)) * 1000 +
((tp.millitm - LastWtime.millitm) / 1000);
}
void Yap_walltime_interval(Int *now,Int *interval)
{
struct _timeb tp;
_ftime(&tp);
*now = (tp.time - StartOfWTimes.time) * 1000 +
(tp.millitm - StartOfWTimes.millitm);
*interval = (tp.time - LastWtime.time) * 1000 +
(tp.millitm - LastWtime.millitm) ;
LastWtime.millitm = tp.millitm;
LastWtime.time = tp.time;
}
#elif HAVE_TIMES
static clock_t StartOfWTimes;
2015-06-17 23:49:02 +01:00
#define LastWtime (*(clock_t *)GLOBAL_LastWtimePtr)
/* store user time in this variable */
static void
InitWTime (void)
{
StartOfWTimes = times(NULL);
}
static void
InitLastWtime(void) {
2015-06-17 23:49:02 +01:00
GLOBAL_LastWtimePtr = (void *)Yap_AllocCodeSpace(sizeof(clock_t));
LastWtime = StartOfWTimes;
}
Int
Yap_walltime (void)
{
clock_t t;
t = times(NULL);
return ((t - StartOfWTimes)*1000 / TicksPerSec));
}
void Yap_walltime_interval(Int *now,Int *interval)
{
clock_t t;
t = times(NULL);
*now = ((t - StartOfWTimes)*1000) / TicksPerSec;
2015-06-17 23:49:02 +01:00
*interval = (t - GLOBAL_LastWtime) * 1000 / TicksPerSec;
}
#endif /* HAVE_TIMES */
#if HAVE_TIME_H
#include <time.h>
#endif
unsigned int current_seed;
static void
InitRandom (void)
{
current_seed = (unsigned int) time (NULL);
#if HAVE_SRAND48
srand48 (current_seed);
#elif HAVE_SRANDOM
srandom (current_seed);
#elif HAVE_SRAND
srand (current_seed);
#endif
}
2013-04-25 23:15:04 +01:00
extern int rand(void);
double
Yap_random (void)
{
#if HAVE_DRAND48
return drand48();
#elif HAVE_RANDOM
/* extern long random (); */
return (((double) random ()) / 0x7fffffffL /* 2**31-1 */);
#elif HAVE_RAND
return (((double) (rand ()) / RAND_MAX));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-13 13:28:17 +01:00
"random not available in this configuration");
return (0.0);
#endif
}
2014-05-28 01:12:51 +01:00
#if HAVE_RANDOM
static Int
p_init_random_state ( USES_REGS1 )
{
register Term t0 = Deref (ARG1);
char *old, *new;
2014-05-28 01:12:51 +01:00
if (IsVarTerm (t0)) {
return(Yap_unify(ARG1,MkIntegerTerm((Int)current_seed)));
}
if(!IsNumTerm (t0))
return (FALSE);
if (IsIntTerm (t0))
current_seed = (unsigned int) IntOfTerm (t0);
else if (IsFloatTerm (t0))
current_seed = (unsigned int) FloatOfTerm (t0);
else
current_seed = (unsigned int) LongIntOfTerm (t0);
2015-01-20 03:00:42 +00:00
new = (char *) malloc(256);
2014-05-28 01:12:51 +01:00
old = initstate(random(), new, 256);
return Yap_unify(ARG2, MkIntegerTerm((Int)old)) &&
2015-04-24 17:03:44 +01:00
Yap_unify(ARG3, MkIntegerTerm((Int)new));
2014-05-28 01:12:51 +01:00
}
static Int
p_set_random_state ( USES_REGS1 )
{
register Term t0 = Deref (ARG1);
2014-05-28 01:54:28 +01:00
char *old, * new;
2014-05-28 01:12:51 +01:00
if (IsVarTerm (t0)) {
return FALSE;
}
if (IsIntegerTerm (t0))
new = (char *) IntegerOfTerm (t0);
else
return FALSE;
2014-05-28 01:40:03 +01:00
old = setstate( new );
2014-05-28 01:12:51 +01:00
return Yap_unify(ARG2, MkIntegerTerm((Int)old));
}
2014-05-28 01:54:28 +01:00
static Int
p_release_random_state ( USES_REGS1 )
{
register Term t0 = Deref (ARG1);
char *old;
if (IsVarTerm (t0)) {
return FALSE;
}
if (IsIntegerTerm (t0))
old = (char *) IntegerOfTerm (t0);
else
return FALSE;
free( old );
return TRUE;
}
2014-05-28 01:12:51 +01:00
#endif
static Int
2015-06-17 23:49:02 +01:00
Srandom ( USES_REGS1 )
{
register Term t0 = Deref (ARG1);
if (IsVarTerm (t0)) {
return(Yap_unify(ARG1,MkIntegerTerm((Int)current_seed)));
}
if(!IsNumTerm (t0))
return (FALSE);
if (IsIntTerm (t0))
current_seed = (unsigned int) IntOfTerm (t0);
else if (IsFloatTerm (t0))
current_seed = (unsigned int) FloatOfTerm (t0);
else
current_seed = (unsigned int) LongIntOfTerm (t0);
2015-07-06 12:03:16 +01:00
#if HAVE_SRAND48
srand48(current_seed);
#elif HAVE_SRANDOM
srandom(current_seed);
#elif HAVE_SRAND
srand(current_seed);
#endif
return (TRUE);
}
2014-03-15 23:47:29 +00:00
#if HAVE_SIGNAL_H
#include <signal.h>
#ifdef MPW
#define signal sigset
#endif
#ifdef MSH
#define SIGFPE SIGDIV
#endif
2013-04-25 23:15:04 +01:00
static void InitSignals(void);
2010-06-17 08:20:34 +01:00
#define PLSIG_PREPARED 0x01 /* signal is prepared */
#define PLSIG_THROW 0x02 /* throw signal(num, name) */
#define PLSIG_SYNC 0x04 /* call synchronously */
#define PLSIG_NOFRAME 0x08 /* Do not create a Prolog frame */
#define SIG_PROLOG_OFFSET 32 /* Start of Prolog signals */
#define SIG_EXCEPTION (SIG_PROLOG_OFFSET+0)
2015-06-18 07:55:07 +01:00
#ifdef ATOMGC
2010-06-17 08:20:34 +01:00
#define SIG_ATOM_GC (SIG_PROLOG_OFFSET+1)
#endif
#define SIG_GC (SIG_PROLOG_OFFSET+2)
2015-06-18 07:55:07 +01:00
#ifdef THREADS
2010-06-17 08:20:34 +01:00
#define SIG_THREAD_SIGNAL (SIG_PROLOG_OFFSET+3)
#endif
#define SIG_FREECLAUSES (SIG_PROLOG_OFFSET+4)
#define SIG_PLABORT (SIG_PROLOG_OFFSET+5)
static struct signame
{ int sig;
const char *name;
int flags;
} signames[] =
2015-04-24 17:03:44 +01:00
{
2010-06-17 08:20:34 +01:00
#ifdef SIGHUP
2015-04-24 17:03:44 +01:00
{ SIGHUP, "hup", 0},
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIGINT, "int", 0},
2010-06-17 08:20:34 +01:00
#ifdef SIGQUIT
2015-04-24 17:03:44 +01:00
{ SIGQUIT, "quit", 0},
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIGILL, "ill", 0},
{ SIGABRT, "abrt", 0},
2014-03-15 23:47:29 +00:00
#if HAVE_SIGFPE
2015-04-24 17:03:44 +01:00
{ SIGFPE, "fpe", PLSIG_THROW},
2014-03-15 23:47:29 +00:00
#endif
2010-06-17 08:20:34 +01:00
#ifdef SIGKILL
2015-04-24 17:03:44 +01:00
{ SIGKILL, "kill", 0},
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIGSEGV, "segv", 0},
2010-06-17 08:20:34 +01:00
#ifdef SIGPIPE
2015-04-24 17:03:44 +01:00
{ SIGPIPE, "pipe", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGALRM
2015-04-24 17:03:44 +01:00
{ SIGALRM, "alrm", PLSIG_THROW},
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIGTERM, "term", 0},
2010-06-17 08:20:34 +01:00
#ifdef SIGUSR1
2015-04-24 17:03:44 +01:00
{ SIGUSR1, "usr1", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGUSR2
2015-04-24 17:03:44 +01:00
{ SIGUSR2, "usr2", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGCHLD
2015-04-24 17:03:44 +01:00
{ SIGCHLD, "chld", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGCONT
2015-04-24 17:03:44 +01:00
{ SIGCONT, "cont", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGSTOP
2015-04-24 17:03:44 +01:00
{ SIGSTOP, "stop", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGTSTP
2015-04-24 17:03:44 +01:00
{ SIGTSTP, "tstp", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGTTIN
2015-04-24 17:03:44 +01:00
{ SIGTTIN, "ttin", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGTTOU
2015-04-24 17:03:44 +01:00
{ SIGTTOU, "ttou", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGTRAP
2015-04-24 17:03:44 +01:00
{ SIGTRAP, "trap", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGBUS
2015-04-24 17:03:44 +01:00
{ SIGBUS, "bus", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGSTKFLT
2015-04-24 17:03:44 +01:00
{ SIGSTKFLT, "stkflt", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGURG
2015-04-24 17:03:44 +01:00
{ SIGURG, "urg", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGIO
2015-04-24 17:03:44 +01:00
{ SIGIO, "io", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGPOLL
2015-04-24 17:03:44 +01:00
{ SIGPOLL, "poll", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGXCPU
2015-04-24 17:03:44 +01:00
{ SIGXCPU, "xcpu", PLSIG_THROW},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGXFSZ
2015-04-24 17:03:44 +01:00
{ SIGXFSZ, "xfsz", PLSIG_THROW},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGVTALRM
2015-04-24 17:03:44 +01:00
{ SIGVTALRM, "vtalrm", PLSIG_THROW},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGPROF
2015-04-24 17:03:44 +01:00
{ SIGPROF, "prof", 0},
2010-06-17 08:20:34 +01:00
#endif
#ifdef SIGPWR
2015-04-24 17:03:44 +01:00
{ SIGPWR, "pwr", 0},
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIG_EXCEPTION, "prolog:exception", 0 },
2010-06-17 08:20:34 +01:00
#ifdef SIG_ATOM_GC
2015-04-24 17:03:44 +01:00
{ SIG_ATOM_GC, "prolog:atom_gc", 0 },
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ SIG_GC, "prolog:gc", 0 },
2010-06-17 08:20:34 +01:00
#ifdef SIG_THREAD_SIGNAL
2015-04-24 17:03:44 +01:00
{ SIG_THREAD_SIGNAL, "prolog:thread_signal", 0 },
2010-06-17 08:20:34 +01:00
#endif
2015-04-24 17:03:44 +01:00
{ -1, NULL, 0}
};
2010-06-17 08:20:34 +01:00
/* SWI emulation */
int
Yap_signal_index(const char *name)
{ struct signame *sn = signames;
char tmp[12];
2015-01-20 03:00:42 +00:00
if ( strncmp(name, "SIG", 3) == 0 && strlen(name) < 12 )
2010-06-17 08:20:34 +01:00
{ char *p = (char *)name+3, *q = tmp;
while ((*q++ = tolower(*p++))) {};
name = tmp;
}
for( ; sn->name; sn++ )
2015-04-24 17:03:44 +01:00
{ if ( !strcmp(sn->name, name) )
return sn->sig;
}
2010-06-17 08:20:34 +01:00
return -1;
}
#if HAVE_SIGINFO_H
#include <siginfo.h>
#endif
#if HAVE_SYS_UCONTEXT_H
#include <sys/ucontext.h>
#endif
2014-03-15 23:47:29 +00:00
#if HAVE_SIGSEGV
static void
SearchForTrailFault(void *ptr, int sure)
{
/* If the TRAIL is very close to the top of mmaped allocked space,
then we can try increasing the TR space and restarting the
instruction. In the worst case, the system will
crash again
2015-04-24 17:03:44 +01:00
*/
2014-03-15 23:47:29 +00:00
#if OS_HANDLES_TR_OVERFLOW && !USE_SYSTEM_MALLOC
2015-01-20 03:00:42 +00:00
if ((ptr > (void *)LOCAL_TrailTop-1024 &&
2014-03-15 23:47:29 +00:00
TR < (tr_fr_ptr) LOCAL_TrailTop+(64*1024))) {
if (!Yap_growtrail(64*1024, TRUE)) {
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_TRAIL, TermNil, "YAP failed to reserve %ld bytes in growtrail", K64);
2014-03-15 23:47:29 +00:00
}
/* just in case, make sure the OS keeps the signal handler. */
/* my_signal_info(SIGSEGV, HandleSIGSEGV); */
} else
#endif /* OS_HANDLES_TR_OVERFLOW */
if (sure)
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
2014-03-15 23:47:29 +00:00
"tried to access illegal address %p!!!!", ptr);
else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
2014-03-15 23:47:29 +00:00
"likely bug in YAP, segmentation violation");
}
/* This routine believes there is a continuous space starting from the
HeapBase and ending on TrailTop */
static void
2014-03-15 23:47:29 +00:00
HandleSIGSEGV(int sig, void *sipv, void *uap)
{
2014-03-16 00:52:43 +00:00
CACHE_REGS
2015-04-24 17:03:44 +01:00
void *ptr = TR;
2014-03-15 23:47:29 +00:00
int sure = FALSE;
if (LOCAL_PrologMode & ExtendStackMode) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "OS memory allocation crashed at address %p, bailing out\n",LOCAL_TrailTop);
2014-03-15 23:47:29 +00:00
}
#if (defined(__svr4__) || defined(__SVR4))
siginfo_t *sip = sipv;
if (
sip->si_code != SI_NOINFO &&
2014-03-15 23:47:29 +00:00
sip->si_code == SEGV_MAPERR) {
ptr = sip->si_addr;
sure = TRUE;
}
2014-03-15 23:47:29 +00:00
#elif __linux__
siginfo_t *sip = sipv;
ptr = sip->si_addr;
sure = TRUE;
#endif
SearchForTrailFault( ptr, sure );
}
2014-03-15 23:47:29 +00:00
#endif /* SIGSEGV */
yap_error_number
Yap_MathException__( USES_REGS1 )
{
#if HAVE_FETESTEXCEPT
int raised;
// #pragma STDC FENV_ACCESS ON
if ((raised = fetestexcept( FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)) ) {
2015-04-24 17:03:44 +01:00
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
2014-10-28 12:56:26 +00:00
#elif _WIN32 && FALSE
unsigned int raised;
int err;
2015-04-24 17:03:44 +01:00
// Show original FP control word and do calculation.
err = _controlfp_s(&raised, 0, 0);
if (err) {
return EVALUATION_ERROR_UNDEFINED;
}
if (raised ) {
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
#elif (defined(__svr4__) || defined(__SVR4))
switch(sip->si_code) {
case FPE_INTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_INTOVF:
return EVALUATION_ERROR_INT_OVERFLOW;
break;
case FPE_FLTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_FLTOVF:
return EVALUATION_ERROR_FLOAT_OVERFLOW;
break;
case FPE_FLTUND:
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
break;
case FPE_FLTRES:
case FPE_FLTINV:
case FPE_FLTSUB:
default:
return EVALUATION_ERROR_UNDEFINED;
}
set_fpu_exceptions(0);
#endif
return LOCAL_matherror;
}
static Int
p_fpe_error( USES_REGS1 )
{
Yap_Error(LOCAL_matherror, LOCAL_mathtt, LOCAL_mathstring);
LOCAL_matherror = YAP_NO_ERROR;
LOCAL_mathtt = TermNil;
LOCAL_mathstring = NULL;
return FALSE;
}
#if HAVE_SIGFPE
static void
HandleMatherr(int sig, void *sipv, void *uapv)
{
CACHE_REGS
2015-04-24 17:03:44 +01:00
LOCAL_matherror = Yap_MathException( );
/* reset the registers so that we don't have trash in abstract machine */
Yap_external_signal( worker_id, YAP_FPE_SIGNAL );
}
2014-03-15 23:47:29 +00:00
#endif /* SIGFPE */
typedef void (*signal_handler_t)(int, void *, void *);
2015-01-20 03:00:42 +00:00
#if HAVE_SIGACTION
static void
my_signal_info(int sig, void * handler)
{
struct sigaction sigact;
sigact.sa_handler = handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigaction(sig,&sigact,NULL);
}
static void
my_signal(int sig, void * handler)
{
struct sigaction sigact;
2014-03-15 23:47:29 +00:00
sigact.sa_handler= (void *)handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(sig,&sigact,NULL);
}
#else
static void
my_signal(int sig, void *handler)
{
signal(sig, handler);
}
static void
my_signal_info(int sig, void *handler)
{
2014-03-15 23:47:29 +00:00
if(signal(sig, (void *)handler) == SIG_ERR)
exit(1);
}
2014-03-15 23:47:29 +00:00
#endif
2015-01-20 03:00:42 +00:00
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
static RETSIGTYPE
2014-03-15 23:47:29 +00:00
ReceiveSignal (int s, void *x, void *y)
{
CACHE_REGS
2015-04-24 17:03:44 +01:00
LOCAL_PrologMode |= InterruptMode;
2014-09-03 04:24:01 +01:00
my_signal (s, ReceiveSignal);
switch (s)
{
2015-04-24 17:03:44 +01:00
case SIGINT:
// always direct SIGINT to console
Yap_external_signal( 0, YAP_INT_SIGNAL );
break;
2015-04-24 17:03:44 +01:00
case SIGALRM:
Yap_external_signal( worker_id, YAP_ALARM_SIGNAL );
break;
2015-04-24 17:03:44 +01:00
case SIGVTALRM:
Yap_external_signal( worker_id, YAP_VTALARM_SIGNAL );
break;
#ifndef MPW
2014-03-15 23:47:29 +00:00
#ifdef HAVE_SIGFPE
case SIGFPE:
Yap_external_signal( worker_id, YAP_FPE_SIGNAL );
break;
#endif
2014-03-15 23:47:29 +00:00
#endif
#if !defined(LIGHT) && !defined(_WIN32)
/* These signals are not handled by WIN32 and not the Macintosh */
case SIGQUIT:
case SIGKILL:
LOCAL_PrologMode &= ~InterruptMode;
2015-09-25 10:57:26 +01:00
Yap_Error(INTERRUPT_EVENT,MkIntTerm(s),NULL);
break;
#endif
#ifdef SIGUSR1
case SIGUSR1:
/* force the system to creep */
Yap_external_signal ( worker_id, YAP_USR1_SIGNAL);
break;
#endif /* defined(SIGUSR1) */
#ifdef SIGUSR2
case SIGUSR2:
/* force the system to creep */
Yap_external_signal ( worker_id, YAP_USR2_SIGNAL);
break;
#endif /* defined(SIGUSR2) */
#ifdef SIGPIPE
case SIGPIPE:
/* force the system to creep */
Yap_external_signal ( worker_id, YAP_PIPE_SIGNAL);
break;
#endif /* defined(SIGPIPE) */
#ifdef SIGHUP
case SIGHUP:
/* force the system to creep */
2013-03-04 02:29:02 +00:00
/* Just ignore SUGHUP Yap_signal (YAP_HUP_SIGNAL); */
break;
#endif /* defined(SIGHUP) */
default:
2014-03-04 12:02:26 +00:00
fprintf(stderr, "\n[ Unexpected signal ]\n");
exit (s);
}
2014-09-03 04:24:01 +01:00
LOCAL_PrologMode &= ~InterruptMode;
}
#endif
#if (_MSC_VER || defined(__MINGW32__))
static BOOL WINAPI
MSCHandleSignal(DWORD dwCtrlType) {
#if THREADS
if (REMOTE_InterruptsDisabled(0)) {
#else
2015-04-24 17:03:44 +01:00
if (LOCAL_InterruptsDisabled) {
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
switch(dwCtrlType) {
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
#if THREADS
2015-04-24 17:03:44 +01:00
Yap_external_signal(0, YAP_WINTIMER_SIGNAL);
REMOTE_PrologMode(0) |= InterruptMode;
#else
2015-04-24 17:03:44 +01:00
Yap_signal(YAP_WINTIMER_SIGNAL);
LOCAL_PrologMode |= InterruptMode;
#endif
2015-04-24 17:03:44 +01:00
return(TRUE);
default:
return(FALSE);
}
}
#endif
2015-04-13 13:28:17 +01:00
2015-04-24 17:03:44 +01:00
/* SIGINT can cause problems, if caught before full initialization */
static void
InitSignals (void)
{
if (GLOBAL_PrologShouldHandleInterrupts) {
2015-01-20 03:00:42 +00:00
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
2015-04-24 17:03:44 +01:00
my_signal (SIGQUIT, ReceiveSignal);
my_signal (SIGKILL, ReceiveSignal);
my_signal (SIGUSR1, ReceiveSignal);
my_signal (SIGUSR2, ReceiveSignal);
my_signal (SIGHUP, ReceiveSignal);
my_signal (SIGALRM, ReceiveSignal);
my_signal (SIGVTALRM, ReceiveSignal);
#endif
#ifdef SIGPIPE
2015-04-24 17:03:44 +01:00
my_signal (SIGPIPE, ReceiveSignal);
#endif
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
signal (SIGINT, SIG_IGN);
SetConsoleCtrlHandler(MSCHandleSignal,TRUE);
#else
2015-04-24 17:03:44 +01:00
my_signal (SIGINT, ReceiveSignal);
#endif
2014-03-15 23:47:29 +00:00
#ifdef HAVE_SIGFPE
2015-04-24 17:03:44 +01:00
my_signal (SIGFPE, HandleMatherr);
#endif
2014-03-16 00:52:43 +00:00
#if HAVE_SIGSEGV
2015-04-24 17:03:44 +01:00
my_signal_info (SIGSEGV, HandleSIGSEGV);
#endif
2011-03-30 16:39:09 +01:00
#ifdef YAPOR_COW
2015-04-24 17:03:44 +01:00
signal(SIGCHLD, SIG_IGN); /* avoid ghosts */
#endif
2015-04-24 17:03:44 +01:00
}
}
#endif /* HAVE_SIGNAL */
2015-04-24 17:03:44 +01:00
/* TrueFileName -> Finds the true name of a file */
#ifdef __MINGW32__
#include <ctype.h>
#endif
2015-04-24 17:03:44 +01:00
static int
volume_header(char *file)
{
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
char *ch = file;
int c;
2015-04-24 17:03:44 +01:00
while ((c = ch[0]) != '\0') {
if (isalnum(c)) ch++;
else return(c == ':');
}
#endif
2015-04-24 17:03:44 +01:00
return(FALSE);
}
2015-04-24 17:03:44 +01:00
int
Yap_volume_header(char *file)
{
return volume_header(file);
}
2015-04-24 17:03:44 +01:00
const char * Yap_getcwd(const char *cwd, size_t cwdlen)
{
#if _WIN32 || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
if (GetCurrentDirectory(cwdlen, (char *)cwd) == 0)
{
Yap_WinError("GetCurrentDirectory failed" );
return NULL;
}
return (char *)cwd;
2015-06-17 23:49:02 +01:00
#elif __ANDROID__
2015-04-24 17:03:44 +01:00
if (GLOBAL_AssetsWD) {
return strncpy( (char *)cwd, (const char *)GLOBAL_AssetsWD, cwdlen);
}
#endif
return getcwd((char *)cwd, cwdlen);
}
2015-06-17 23:49:02 +01:00
static Int
working_directory(USES_REGS1)
{
char dir[YAP_FILENAME_MAX+1];
Term t1 = Deref(ARG1), t2;
if ( !IsVarTerm( t1 ) && !IsAtomTerm(t1) ) {
Yap_Error(TYPE_ERROR_ATOM, t1, "working_directory");
}
if (!Yap_unify( t1, MkAtomTerm(Yap_LookupAtom(Yap_getcwd(dir,YAP_FILENAME_MAX )))) )
return false;
t2 = Deref(ARG2);
if ( IsVarTerm( t2 ) ) {
Yap_Error(INSTANTIATION_ERROR, t2, "working_directory");
2015-07-06 12:03:16 +01:00
}
2015-06-17 23:49:02 +01:00
if ( !IsAtomTerm(t2) ) {
Yap_Error(TYPE_ERROR_ATOM, t2, "working_directory");
}
ChDir(RepAtom(AtomOfTerm(t2))->StrOfAE);
return true;
}
2015-04-24 17:03:44 +01:00
static char *
expandWithPrefix(const char *source, const char *root, char *result)
{
char *work;
char ares1[YAP_FILENAME_MAX+1];
work = expandVars( source, ares1, YAP_FILENAME_MAX);
// expand names first
2015-06-17 23:49:02 +01:00
if (root && !Yap_IsAbsolutePath( source ) ) {
2015-04-24 17:03:44 +01:00
char ares2[YAP_FILENAME_MAX+1];
strncpy( ares2, root, YAP_FILENAME_MAX );
strncat( ares2, "/", YAP_FILENAME_MAX );
strncat( ares2, work, YAP_FILENAME_MAX );
2015-06-17 23:49:02 +01:00
return Yap_AbsoluteFile( ares2, result );
2015-04-24 17:03:44 +01:00
} else {
// expand path
return myrealpath( work, result);
}
}
/** Yap_trueFileName: tries to generate the true name of file
2015-07-06 12:03:16 +01:00
*
*
2015-04-24 17:03:44 +01:00
* @param isource the proper file
* @param idef the default name fo rthe file, ie, startup.yss
* @param root the prefix
* @param result the output
* @param access verify whether the file has access permission
* @param ftype saved state, object, saved file, prolog file
* @param expand_root expand $ ~, etc
* @param in_lib library file
2015-07-06 12:03:16 +01:00
*
* @return
2015-04-24 17:03:44 +01:00
*/
bool
Yap_trueFileName (const char *isource, const char * idef, const char *iroot, char *result, bool access, file_type_t ftype, bool expand_root, bool in_lib)
{
2015-07-06 12:03:16 +01:00
char save_buffer[YAP_FILENAME_MAX+1];
const char *root, *source = isource;
2015-04-24 17:03:44 +01:00
int rc = FAIL_RESTORE;
int try = 0;
while ( rc == FAIL_RESTORE) {
bool done = false;
2015-07-06 12:03:16 +01:00
// { CACHE_REGS __android_log_print(ANDROID_LOG_ERROR, __FUNCTION__, "try=%d %s %s", try, isource, iroot) ; }
2015-04-24 17:03:44 +01:00
switch (try++) {
case 0: // path or file name is given;
2015-07-06 12:03:16 +01:00
root = iroot;
if (iroot || isource) {
source = ( isource ? isource : idef ) ;
} else {
2015-04-24 17:03:44 +01:00
done = true;
}
2015-04-24 17:03:44 +01:00
break;
case 1: // library directory is given in command line
if ( in_lib && ftype == YAP_SAVED_STATE) {
root = iroot;
2015-07-06 12:03:16 +01:00
source = ( isource ? isource : idef ) ;
2015-04-24 17:03:44 +01:00
} else
done = true;
break;
case 2: // use environment variable YAPLIBDIR
#if HAVE_GETENV
if ( in_lib) {
if (ftype == YAP_SAVED_STATE || ftype == YAP_OBJ) {
2015-07-06 12:03:16 +01:00
root = getenv("YAPLIBDIR");
2015-04-24 17:03:44 +01:00
} else {
root = getenv("YAPSHAREDIR");
}
2015-07-06 12:03:16 +01:00
source = ( isource ? isource : idef ) ;
2015-04-24 17:03:44 +01:00
} else
done = true;
break;
#else
2015-04-24 17:03:44 +01:00
done = true;
#endif
2015-04-24 17:03:44 +01:00
break;
case 3: // use compilation variable YAPLIBDIR
if ( in_lib) {
2015-07-06 12:03:16 +01:00
source = ( isource ? isource : idef ) ;
2015-04-24 17:03:44 +01:00
if (ftype == YAP_PL || ftype == YAP_QLY) {
root = YAP_SHAREDIR;
} else {
root = YAP_LIBDIR;
}
} else
done = true;
break;
2015-04-24 17:03:44 +01:00
case 4: // WIN stuff: registry
#if __WINDOWS__
2015-07-06 12:03:16 +01:00
if ( in_lib) {
2015-04-24 17:03:44 +01:00
source = ( ftype == YAP_PL || ftype == YAP_QLY ? "library" : "startup" ) ;
source = Yap_RegistryGetString( source );
root = NULL;
} else
#endif
2015-04-24 17:03:44 +01:00
done = true;
break;
2015-04-13 13:28:17 +01:00
2015-04-24 17:03:44 +01:00
case 5: // search from the binary
{
#ifndef __ANDROID__
2015-04-24 17:03:44 +01:00
done = true;
break;
#endif
2015-04-24 17:03:44 +01:00
const char *pt = Yap_FindExecutable();
2015-04-24 17:03:44 +01:00
if (pt) {
source = ( ftype == YAP_SAVED_STATE || ftype == YAP_OBJ ? "../../lib/Yap" : "../../share/Yap" ) ;
if (Yap_trueFileName(source, NULL, pt, save_buffer, access, ftype, expand_root, in_lib) )
root = save_buffer;
2015-07-06 12:03:16 +01:00
else
2015-04-24 17:03:44 +01:00
done = true;
} else {
done = true;
}
source = ( isource ? isource : idef ) ;
}
break;
case 6: // default, try current directory
if (!isource && ftype == YAP_SAVED_STATE)
source = idef;
root = NULL;
break;
default:
return false;
}
2015-07-06 12:03:16 +01:00
2015-04-24 17:03:44 +01:00
if (done)
continue;
if (expand_root && root) {
root = expandWithPrefix( root, NULL, save_buffer );
}
// { CACHE_REGS __android_log_print(ANDROID_LOG_ERROR, __FUNCTION__, "root= %s %s ", root, source) ; }
char *work = expandWithPrefix( source, root, result );
2015-07-06 12:03:16 +01:00
2015-04-24 17:03:44 +01:00
// expand names in case you have
// to add a prefix
if ( !access || exists( work ) )
return true; // done
}
return false;
}
2015-04-13 13:28:17 +01:00
2015-04-24 17:03:44 +01:00
int
Yap_TrueFileName (const char *source, char *result, int in_lib)
{
2015-07-06 12:03:16 +01:00
return Yap_trueFileName (source, NULL, NULL, result, true, YAP_PL, true, in_lib);
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
int
Yap_TruePrefixedFileName (const char *source, const char *root, char *result, int in_lib)
{
2015-07-06 12:03:16 +01:00
return Yap_trueFileName (source, NULL, root, result, true, YAP_PL, true, in_lib);
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
static Int
p_true_file_name ( USES_REGS1 )
{
Term t = Deref(ARG1);
2015-01-20 03:00:42 +00:00
2015-04-24 17:03:44 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR,t,"argument to true_file_name unbound");
return FALSE;
}
if (!IsAtomTerm(t)) {
Yap_Error(TYPE_ERROR_ATOM,t,"argument to true_file_name");
return FALSE;
}
2015-07-06 12:03:16 +01:00
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, NULL, LOCAL_FileNameBuf, true, YAP_PL, false, false))
2015-04-24 17:03:44 +01:00
return FALSE;
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)));
}
2013-11-08 12:43:07 +00:00
2015-04-24 17:03:44 +01:00
static Int
p_expand_file_name ( USES_REGS1 )
{
Term t = Deref(ARG1);
2015-01-20 03:00:42 +00:00
2015-04-24 17:03:44 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR,t,"argument to true_file_name unbound");
return FALSE;
}
if (!IsAtomTerm(t)) {
Yap_Error(TYPE_ERROR_ATOM,t,"argument to true_file_name");
return FALSE;
}
2015-07-06 12:03:16 +01:00
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, NULL, LOCAL_FileNameBuf, true, YAP_PL, true, false))
2015-04-24 17:03:44 +01:00
return false;
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)));
2013-11-08 12:43:07 +00:00
}
2015-04-24 17:03:44 +01:00
static Int
p_true_file_name3 ( USES_REGS1 )
{
Term t = Deref(ARG1), t2 = Deref(ARG2);
char *root = NULL;
2015-01-20 03:00:42 +00:00
2015-04-24 17:03:44 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR,t,"argument to true_file_name unbound");
return FALSE;
}
if (!IsAtomTerm(t)) {
2015-04-24 17:03:44 +01:00
Yap_Error(TYPE_ERROR_ATOM,t,"argument to true_file_name");
return FALSE;
}
2015-04-24 17:03:44 +01:00
if (!IsVarTerm(t2)) {
if (!IsAtomTerm(t)) {
Yap_Error(TYPE_ERROR_ATOM,t2,"argument to true_file_name");
return FALSE;
}
root = RepAtom(AtomOfTerm(t2))->StrOfAE;
}
2015-07-06 12:03:16 +01:00
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, root, LOCAL_FileNameBuf, true, YAP_PL, false, false))
2015-04-24 17:03:44 +01:00
return FALSE;
return Yap_unify(ARG3, MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)));
}
2015-04-24 17:03:44 +01:00
/* Executes $SHELL under Prolog */
/** @pred sh
2014-09-15 19:10:49 +01:00
2015-04-24 17:03:44 +01:00
Creates a new shell interaction.
2015-01-20 03:00:42 +00:00
2015-04-24 17:03:44 +01:00
*/
static Int
p_sh ( USES_REGS1 )
{ /* sh */
#ifdef HAVE_SYSTEM
2015-04-24 17:03:44 +01:00
char *shell;
shell = (char *) getenv ("SHELL");
if (shell == NULL)
shell = "/bin/sh";
if (system (shell) < 0) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "%s in sh/0", strerror(errno));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil, "in sh/0");
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
return TRUE;
#else
#ifdef MSH
2015-04-24 17:03:44 +01:00
register char *shell;
shell = "msh -i";
system (shell);
return (TRUE);
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL,TermNil,"sh not available in this configuration");
2015-04-24 17:03:44 +01:00
return(FALSE);
#endif /* MSH */
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/** shell(+Command:text, -Status:integer) is det.
2014-03-06 02:09:48 +00:00
2015-04-24 17:03:44 +01:00
Run an external command and wait for its completion.
*/
static Int
p_shell ( USES_REGS1 )
{ /* '$shell'(+SystCommand) */
2014-09-15 19:10:49 +01:00
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
char *cmd;
term_t A1 = Yap_InitSlot(ARG1);
if ( PL_get_chars(A1, &cmd, CVT_ALL|REP_FN|CVT_EXCEPTION) )
{ int rval = System(cmd);
2014-03-06 02:09:48 +00:00
2015-04-24 17:03:44 +01:00
return rval == 0;
}
2014-03-06 02:09:48 +00:00
2015-04-24 17:03:44 +01:00
return FALSE;
#else
2015-01-20 03:00:42 +00:00
#if HAVE_SYSTEM
2015-04-24 17:03:44 +01:00
char *shell;
register int bourne = FALSE;
Term t1 = Deref (ARG1);
const char *cmd;
shell = (char *) getenv ("SHELL");
if (!strcmp (shell, "/bin/sh"))
bourne = TRUE;
if (shell == NIL)
bourne = TRUE;
if (IsAtomTerm(t1))
cmd = RepAtom(AtomOfTerm(t1))->StrOfAE;
else if (IsStringTerm(t1))
cmd = StringOfTerm(t1);
else
return FALSE;
/* Yap_CloseStreams(TRUE); */
if (bourne)
return system( cmd ) == 0;
else {
int status = -1;
int child = fork ();
if (child == 0) { /* let the children go */
if (!execl (shell, shell, "-c", cmd , NULL)) {
exit(-1);
}
exit(TRUE);
}
2015-04-24 17:03:44 +01:00
{ /* put the father on wait */
int result = child < 0 ||
/* vsc:I am not sure this is used, Stevens say wait returns an integer.
#if NO_UNION_WAIT
*/
wait ((&status)) != child ||
/*
#else
wait ((union wait *) (&status)) != child ||
#endif
*/
status == 0;
return result;
}
}
#else /* HAVE_SYSTEM */
#ifdef MSH
2015-04-24 17:03:44 +01:00
register char *shell;
shell = "msh -i";
/* Yap_CloseStreams(); */
system (shell);
return TRUE;
#else
2015-09-25 10:57:26 +01:00
Yap_Error (SYSTEM_ERROR_INTERNAL,TermNil,"shell not available in this configuration");
2015-04-24 17:03:44 +01:00
return FALSE;
#endif
#endif /* HAVE_SYSTEM */
#endif /* _MSC_VER */
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/** system(+Command:text).
2014-09-15 19:10:49 +01:00
2015-04-24 17:03:44 +01:00
Run an external command.
*/
2014-09-15 19:10:49 +01:00
2015-04-24 17:03:44 +01:00
static Int
p_system ( USES_REGS1 )
{ /* '$system'(+SystCommand) */
2014-03-16 00:52:43 +00:00
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
char *cmd;
term_t A1 = Yap_InitSlot(ARG1);
if ( PL_get_chars(A1, &cmd, CVT_ALL|REP_FN|CVT_EXCEPTION) )
{ STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
cmd, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
2015-09-25 10:57:26 +01:00
Yap_Error( SYSTEM_ERROR_INTERNAL, ARG1, "CreateProcess failed (%d).\n", GetLastError() );
2015-04-24 17:03:44 +01:00
return FALSE;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
2014-03-16 00:52:43 +00:00
2015-04-24 17:03:44 +01:00
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
2014-03-16 00:52:43 +00:00
2015-04-24 17:03:44 +01:00
return TRUE;
}
2014-03-16 00:52:43 +00:00
2015-04-24 17:03:44 +01:00
return FALSE;
2014-03-16 00:52:43 +00:00
#elif HAVE_SYSTEM
2015-04-24 17:03:44 +01:00
Term t1 = Deref (ARG1);
const char *s;
2015-04-24 17:03:44 +01:00
if (IsVarTerm(t1)) {
Yap_Error(INSTANTIATION_ERROR,t1,"argument to system/1 unbound");
return FALSE;
2015-04-24 17:03:44 +01:00
} else if (IsAtomTerm(t1)) {
s = RepAtom(AtomOfTerm(t1))->StrOfAE;
} else if (IsStringTerm(t1)) {
s = StringOfTerm(t1);
} else {
if (!Yap_GetName (LOCAL_FileNameBuf, YAP_FILENAME_MAX, t1)) {
Yap_Error(TYPE_ERROR_ATOM,t1,"argument to system/1");
return FALSE;
}
s = LOCAL_FileNameBuf;
}
2015-04-24 17:03:44 +01:00
/* Yap_CloseStreams(TRUE); */
#if _MSC_VER
2015-04-24 17:03:44 +01:00
_flushall();
#endif
2015-04-24 17:03:44 +01:00
if (system (s)) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM,t1,"%s in system(%s)", strerror(errno), s);
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM,t1,"in system(%s)", s);
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
return TRUE;
#else
#ifdef MSH
2015-04-24 17:03:44 +01:00
register char *shell;
shell = "msh -i";
/* Yap_CloseStreams(); */
system (shell);
return (TRUE);
#undef command
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL,TermNil,"sh not available in this machine");
2015-04-24 17:03:44 +01:00
return(FALSE);
#endif
#endif /* HAVE_SYSTEM */
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/* Rename a file */
/** @pred rename(+ _F_,+ _G_)
2014-09-15 19:10:49 +01:00
2015-04-24 17:03:44 +01:00
Renames file _F_ to _G_.
*/
static Int
p_mv ( USES_REGS1 )
{ /* rename(+OldName,+NewName) */
#if HAVE_LINK
2015-04-24 17:03:44 +01:00
int r;
char oldname[YAP_FILENAME_MAX], newname[YAP_FILENAME_MAX];
Term t1 = Deref (ARG1);
Term t2 = Deref (ARG2);
if (IsVarTerm(t1)) {
Yap_Error(INSTANTIATION_ERROR, t1, "first argument to rename/2 unbound");
} else if (!IsAtomTerm(t1)) {
Yap_Error(TYPE_ERROR_ATOM, t1, "first argument to rename/2 not atom");
}
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t2, "second argument to rename/2 unbound");
} else if (!IsAtomTerm(t2)) {
Yap_Error(TYPE_ERROR_ATOM, t2, "second argument to rename/2 not atom");
}
2015-07-06 12:03:16 +01:00
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t1))->StrOfAE, NULL, NULL, oldname, true, YAP_STD, true, false))
2015-04-24 17:03:44 +01:00
return FALSE;
2015-07-06 12:03:16 +01:00
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t2))->StrOfAE, NULL, NULL, oldname, true, YAP_STD, true, false))
2015-04-24 17:03:44 +01:00
return FALSE;
if ((r = link (oldname, newname)) == 0 && (r = unlink (oldname)) != 0)
unlink (newname);
if (r != 0) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM,t2,"%s in rename(%s,%s)", strerror(errno),oldname,newname);
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM,t2,"in rename(%s,%s)",oldname,newname);
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
return TRUE;
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL,TermNil,"rename/2 not available in this machine");
2015-04-24 17:03:44 +01:00
return (FALSE);
#endif
2015-04-24 17:03:44 +01:00
}
#ifdef MAC
2015-04-24 17:03:44 +01:00
void
Yap_SetTextFile (name)
char *name;
{
#ifdef MACC
2015-04-24 17:03:44 +01:00
SetFileType (name, 'TEXT');
SetFileSignature (name, 'EDIT');
#else
2015-04-24 17:03:44 +01:00
FInfo f;
FInfo *p = &f;
GetFInfo (name, 0, p);
p->fdType = 'TEXT';
#ifdef MPW
2015-04-24 17:03:44 +01:00
if (mpwshell)
p->fdCreator = 'MPS\0';
#endif
#ifndef LIGHT
2015-04-24 17:03:44 +01:00
else
p->fdCreator = 'EDIT';
#endif
2015-04-24 17:03:44 +01:00
SetFInfo (name, 0, p);
#endif
2015-04-24 17:03:44 +01:00
}
#endif
2015-04-24 17:03:44 +01:00
/* return YAP's environment */
static Int p_getenv( USES_REGS1 )
{
#if HAVE_GETENV
2015-04-24 17:03:44 +01:00
Term t1 = Deref(ARG1), to;
char *s, *so;
if (IsVarTerm(t1)) {
Yap_Error(INSTANTIATION_ERROR, t1,
"first arg of getenv/2");
return(FALSE);
} else if (!IsAtomTerm(t1)) {
Yap_Error(TYPE_ERROR_ATOM, t1,
"first arg of getenv/2");
return(FALSE);
} else s = RepAtom(AtomOfTerm(t1))->StrOfAE;
if ((so = getenv(s)) == NULL)
return(FALSE);
to = MkAtomTerm(Yap_LookupAtom(so));
return(Yap_unify_constant(ARG2,to));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-24 17:03:44 +01:00
"getenv not available in this configuration");
return (FALSE);
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/* set a variable in YAP's environment */
static Int p_putenv( USES_REGS1 )
{
#if HAVE_PUTENV
2015-04-24 17:03:44 +01:00
Term t1 = Deref(ARG1), t2 = Deref(ARG2);
char *s, *s2, *p0, *p;
if (IsVarTerm(t1)) {
Yap_Error(INSTANTIATION_ERROR, t1,
"first arg to putenv/2");
return(FALSE);
} else if (!IsAtomTerm(t1)) {
Yap_Error(TYPE_ERROR_ATOM, t1,
"first arg to putenv/2");
return(FALSE);
} else s = RepAtom(AtomOfTerm(t1))->StrOfAE;
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t1,
"second arg to putenv/2");
return(FALSE);
} else if (!IsAtomTerm(t2)) {
Yap_Error(TYPE_ERROR_ATOM, t2,
"second arg to putenv/2");
return(FALSE);
} else s2 = RepAtom(AtomOfTerm(t2))->StrOfAE;
while (!(p0 = p = Yap_AllocAtomSpace(strlen(s)+strlen(s2)+3))) {
if (!Yap_growheap(FALSE, MinHeapGap, NULL)) {
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
2015-04-24 17:03:44 +01:00
return FALSE;
}
}
2015-04-24 17:03:44 +01:00
while ((*p++ = *s++) != '\0');
p[-1] = '=';
while ((*p++ = *s2++) != '\0');
if (putenv(p0) == 0)
return TRUE;
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil,
2015-04-24 17:03:44 +01:00
"in putenv(%s)", strerror(errno), p0);
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, TermNil,
2015-04-24 17:03:44 +01:00
"in putenv(%s)", p0);
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-24 17:03:44 +01:00
"putenv not available in this configuration");
return FALSE;
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/* wrapper for alarm system call */
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
static DWORD WINAPI
DoTimerThread(LPVOID targ)
{
Int *time = (Int *)targ;
HANDLE htimer;
LARGE_INTEGER liDueTime;
htimer = CreateWaitableTimer(NULL, FALSE, NULL);
liDueTime.QuadPart = -10000000;
liDueTime.QuadPart *= time[0];
/* add time in usecs */
liDueTime.QuadPart -= time[1]*10;
/* Copy the relative time into a LARGE_INTEGER. */
if (SetWaitableTimer(htimer, &liDueTime,0,NULL,NULL,0) == 0) {
return(FALSE);
}
if (WaitForSingleObject(htimer, INFINITE) != WAIT_OBJECT_0)
fprintf(stderr,"WaitForSingleObject failed (%ld)\n", GetLastError());
Yap_signal (YAP_WINTIMER_SIGNAL);
/* now, say what is going on */
Yap_PutValue(AtomAlarm, MkAtomTerm(AtomTrue));
ExitThread(1);
#if _MSC_VER
2015-04-24 17:03:44 +01:00
return(0L);
#endif
2015-04-24 17:03:44 +01:00
}
#endif
2015-04-24 17:03:44 +01:00
static Int
p_alarm( USES_REGS1 )
{
Term t = Deref(ARG1);
Term t2 = Deref(ARG2);
Int i1, i2;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "alarm/2");
return(FALSE);
}
if (!IsIntegerTerm(t)) {
Yap_Error(TYPE_ERROR_INTEGER, t, "alarm/2");
return(FALSE);
}
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t2, "alarm/2");
return(FALSE);
}
if (!IsIntegerTerm(t2)) {
Yap_Error(TYPE_ERROR_INTEGER, t2, "alarm/2");
return(FALSE);
}
i1 = IntegerOfTerm(t);
i2 = IntegerOfTerm(t2);
if (i1 == 0 && i2 == 0) {
2014-03-04 12:02:26 +00:00
#if _WIN32
2015-04-24 17:03:44 +01:00
Yap_get_signal( YAP_WINTIMER_SIGNAL );
2014-03-04 12:02:26 +00:00
#else
2015-04-24 17:03:44 +01:00
Yap_get_signal( YAP_ALARM_SIGNAL );
2014-03-04 12:02:26 +00:00
#endif
2015-04-24 17:03:44 +01:00
}
#if _MSC_VER || defined(__MINGW32__)
2015-04-24 17:03:44 +01:00
{
Term tout;
Int time[2];
time[0] = i1;
time[1] = i2;
if (time[0] != 0 && time[1] != 0) {
DWORD dwThreadId;
HANDLE hThread;
hThread = CreateThread(
NULL, /* no security attributes */
0, /* use default stack size */
DoTimerThread, /* thread function */
(LPVOID)time, /* argument to thread function */
0, /* use default creation flags */
&dwThreadId); /* returns the thread identifier */
/* Check the return value for success. */
if (hThread == NULL) {
Yap_WinError("trying to use alarm");
}
}
2015-04-24 17:03:44 +01:00
tout = MkIntegerTerm(0);
return Yap_unify(ARG3,tout) && Yap_unify(ARG4,MkIntTerm(0));
}
#elif HAVE_SETITIMER && !SUPPORT_CONDOR
2015-04-24 17:03:44 +01:00
{
struct itimerval new, old;
2015-04-24 17:03:44 +01:00
new.it_interval.tv_sec = 0;
new.it_interval.tv_usec = 0;
new.it_value.tv_sec = i1;
new.it_value.tv_usec = i2;
if (setitimer(ITIMER_REAL, &new, &old) < 0) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "setitimer: %s", strerror(errno));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "setitimer %d", errno);
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
return Yap_unify(ARG3,MkIntegerTerm(old.it_value.tv_sec)) &&
Yap_unify(ARG4,MkIntegerTerm(old.it_value.tv_usec));
}
#elif HAVE_ALARM && !SUPPORT_CONDOR
2015-04-24 17:03:44 +01:00
{
Int left;
Term tout;
2015-04-24 17:03:44 +01:00
left = alarm(i1);
tout = MkIntegerTerm(left);
return Yap_unify(ARG3,tout) && Yap_unify(ARG4,MkIntTerm(0)) ;
}
#else
2015-04-24 17:03:44 +01:00
/* not actually trying to set the alarm */
if (IntegerOfTerm(t) == 0)
return TRUE;
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-24 17:03:44 +01:00
"alarm not available in this configuration");
return FALSE;
#endif
}
2015-04-24 17:03:44 +01:00
static Int
p_virtual_alarm( USES_REGS1 )
{
2015-04-24 17:03:44 +01:00
Term t = Deref(ARG1);
Term t2 = Deref(ARG2);
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "alarm/2");
return(FALSE);
}
if (!IsIntegerTerm(t)) {
Yap_Error(TYPE_ERROR_INTEGER, t, "alarm/2");
return(FALSE);
}
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t2, "alarm/2");
return(FALSE);
}
if (!IsIntegerTerm(t2)) {
Yap_Error(TYPE_ERROR_INTEGER, t2, "alarm/2");
return(FALSE);
}
#if _MSC_VER || defined(__MINGW32__)
{
Term tout;
Int time[2];
time[0] = IntegerOfTerm(t);
time[1] = IntegerOfTerm(t2);
if (time[0] != 0 && time[1] != 0) {
DWORD dwThreadId;
HANDLE hThread;
hThread = CreateThread(
NULL, /* no security attributes */
0, /* use default stack size */
DoTimerThread, /* thread function */
(LPVOID)time, /* argument to thread function */
0, /* use default creation flags */
&dwThreadId); /* returns the thread identifier */
/* Check the return value for success. */
if (hThread == NULL) {
Yap_WinError("trying to use alarm");
}
}
2015-04-24 17:03:44 +01:00
tout = MkIntegerTerm(0);
return Yap_unify(ARG3,tout) && Yap_unify(ARG4,MkIntTerm(0));
}
#elif HAVE_SETITIMER && !SUPPORT_CONDOR
2015-04-24 17:03:44 +01:00
{
struct itimerval new, old;
2015-04-24 17:03:44 +01:00
new.it_interval.tv_sec = 0;
new.it_interval.tv_usec = 0;
new.it_value.tv_sec = IntegerOfTerm(t);
new.it_value.tv_usec = IntegerOfTerm(t2);
if (setitimer(ITIMER_VIRTUAL, &new, &old) < 0) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "setitimer: %s", strerror(errno));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "setitimer %d", errno);
#endif
2015-04-24 17:03:44 +01:00
return FALSE;
}
return Yap_unify(ARG3,MkIntegerTerm(old.it_value.tv_sec)) &&
Yap_unify(ARG4,MkIntegerTerm(old.it_value.tv_usec));
}
#else
2015-04-24 17:03:44 +01:00
/* not actually trying to set the alarm */
if (IntegerOfTerm(t) == 0)
return TRUE;
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
2015-04-24 17:03:44 +01:00
"virtual_alarm not available in this configuration");
return FALSE;
#endif
2015-04-24 17:03:44 +01:00
}
#if HAVE_FPU_CONTROL_H
#include <fpu_control.h>
#endif
2015-04-24 17:03:44 +01:00
/* by default Linux with glibc is IEEE compliant anyway..., but we will pretend it is not. */
static bool
2015-10-18 12:28:02 +01:00
set_fpu_exceptions(Term flag)
2015-04-24 17:03:44 +01:00
{
2015-10-18 12:28:02 +01:00
if (flag == TermTrue) {
#if HAVE_FESETEXCEPTFLAG
fexcept_t excepts;
return fesetexceptflag(&excepts, FE_DIVBYZERO| FE_UNDERFLOW|FE_OVERFLOW) == 0;
#elif HAVE_FEENABLEEXCEPT
/* I shall ignore de-normalization and precision errors */
2015-04-24 17:03:44 +01:00
feenableexcept(FE_DIVBYZERO| FE_INVALID|FE_OVERFLOW);
#elif _WIN32
2015-04-24 17:03:44 +01:00
// Enable zero-divide, overflow and underflow exception
_controlfp_s(0, ~(_EM_ZERODIVIDE|_EM_UNDERFLOW|_EM_OVERFLOW), _MCW_EM); // Line B
#elif defined(__hpux)
# if HAVE_FESETTRAPENABLE
2015-04-24 17:03:44 +01:00
/* From HP-UX 11.0 onwards: */
fesettrapenable(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW);
# else
2015-04-24 17:03:44 +01:00
/*
Up until HP-UX 10.20:
FP_X_INV invalid operation exceptions
FP_X_DZ divide-by-zero exception
FP_X_OFL overflow exception
FP_X_UFL underflow exception
FP_X_IMP imprecise (inexact result)
FP_X_CLEAR simply zero to clear all flags
*/
fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL);
# endif
#endif /* __hpux */
#if HAVE_FPU_CONTROL_H && i386 && defined(__GNUC__)
/* I shall ignore denormalization and precision errors */
int v = _FPU_IEEE & ~(_FPU_MASK_IM|_FPU_MASK_ZM|_FPU_MASK_OM|_FPU_MASK_UM);
_FPU_SETCW(v);
#endif
#if HAVE_FETESTEXCEPT
feclearexcept(FE_ALL_EXCEPT);
#endif
2014-03-15 23:47:29 +00:00
#ifdef HAVE_SIGFPE
my_signal (SIGFPE, HandleMatherr);
2014-01-19 21:15:05 +00:00
#endif
2015-04-24 17:03:44 +01:00
} else {
/* do IEEE arithmetic in the way the big boys do */
#if HAVE_FESETEXCEPTFLAG
fexcept_t excepts;
return fesetexceptflag(&excepts, 0) == 0;
#elif HAVE_FEENABLEEXCEPT
/* I shall ignore de-normalization and precision errors */
feenableexcept(0);
#elif _WIN32
2015-04-24 17:03:44 +01:00
// Enable zero-divide, overflow and underflow exception
_controlfp_s(0, (_EM_ZERODIVIDE|_EM_UNDERFLOW|_EM_OVERFLOW), _MCW_EM); // Line B
#elif defined(__hpux)
# if HAVE_FESETTRAPENABLE
fesettrapenable(FE_ALL_EXCEPT);
# else
fpsetmask(FP_X_CLEAR);
# endif
#endif /* __hpux */
#if HAVE_FPU_CONTROL_H && i386 && defined(__GNUC__)
/* this will probably not work in older releases of Linux */
int v = _FPU_IEEE;
_FPU_SETCW(v);
2015-01-20 03:00:42 +00:00
#endif
2014-03-15 23:47:29 +00:00
#ifdef HAVE_SIGFPE
my_signal (SIGFPE, SIG_IGN);
2014-01-19 21:15:05 +00:00
#endif
2015-04-24 17:03:44 +01:00
}
return true;
}
2015-04-24 17:03:44 +01:00
bool
2015-10-18 12:28:02 +01:00
Yap_set_fpu_exceptions(Term flag)
2015-04-24 17:03:44 +01:00
{
return set_fpu_exceptions(flag);
}
2015-04-24 17:03:44 +01:00
static Int
p_host_type( USES_REGS1 ) {
Term out = MkAtomTerm(Yap_LookupAtom(HOST_ALIAS));
return(Yap_unify(out,ARG1));
}
2015-04-24 17:03:44 +01:00
static Int
p_yap_home( USES_REGS1 ) {
Term out = MkAtomTerm(Yap_LookupAtom(YAP_ROOTDIR));
return(Yap_unify(out,ARG1));
}
2015-04-24 17:03:44 +01:00
static Int
p_yap_paths( USES_REGS1 ) {
Term out1, out2, out3;
const char *env_destdir = getenv("DESTDIR");
char destdir[YAP_FILENAME_MAX+1];
if (env_destdir) {
strncat(destdir, env_destdir, YAP_FILENAME_MAX );
strncat(destdir, "/" YAP_LIBDIR, YAP_FILENAME_MAX );
out1 = MkAtomTerm(Yap_LookupAtom(destdir));
} else {
out1 = MkAtomTerm(Yap_LookupAtom(YAP_LIBDIR));
}
if (env_destdir) {
strncat(destdir, env_destdir, YAP_FILENAME_MAX );
strncat(destdir, "/" YAP_SHAREDIR, YAP_FILENAME_MAX );
out2 = MkAtomTerm(Yap_LookupAtom(destdir));
} else {
out2 = MkAtomTerm(Yap_LookupAtom(YAP_SHAREDIR));
}
if (env_destdir) {
strncat(destdir, env_destdir, YAP_FILENAME_MAX );
strncat(destdir, "/" YAP_BINDIR, YAP_FILENAME_MAX );
out3 = MkAtomTerm(Yap_LookupAtom(destdir));
} else {
out3 = MkAtomTerm(Yap_LookupAtom(YAP_BINDIR));
}
return(Yap_unify(out1,ARG1) &&
Yap_unify(out2,ARG2) &&
Yap_unify(out3,ARG3));
2014-03-04 12:02:26 +00:00
}
2015-04-24 17:03:44 +01:00
static Int
p_log_event( USES_REGS1 ) {
Term in = Deref(ARG1);
Atom at;
2014-06-22 17:35:05 +01:00
2015-04-24 17:03:44 +01:00
if (IsVarTerm(in))
return FALSE;
if (!IsAtomTerm(in))
return FALSE;
at = AtomOfTerm( in );
2014-06-22 17:35:05 +01:00
#if DEBUG
2015-04-24 17:03:44 +01:00
if (IsWideAtom(at) )
fprintf(stderr, "LOG %S\n", RepAtom(at)->WStrOfAE);
else if (IsBlob(at))
return FALSE;
else
fprintf(stderr, "LOG %s\n", RepAtom(at)->StrOfAE);
2014-06-22 17:35:05 +01:00
#endif
2015-04-24 17:03:44 +01:00
if (IsWideAtom(at) || IsBlob(at))
return FALSE;
LOG( " %s ",RepAtom(at)->StrOfAE);
return TRUE;
2014-06-22 17:35:05 +01:00
2015-04-24 17:03:44 +01:00
}
2014-06-22 17:35:05 +01:00
2015-04-24 17:03:44 +01:00
static Int
p_env_separator( USES_REGS1 ) {
#if defined(_WIN32)
2015-04-24 17:03:44 +01:00
return Yap_unify(MkIntegerTerm(';'),ARG1);
#else
2015-04-24 17:03:44 +01:00
return Yap_unify(MkIntegerTerm(':'),ARG1);
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
/*
* This is responsable for the initialization of all machine dependant
* predicates
*/
void
Yap_InitSysbits (void)
{
2015-04-24 17:03:44 +01:00
#if __simplescalar__
{
char *pwd = getenv("PWD");
strncpy(GLOBAL_pwd,pwd,YAP_FILENAME_MAX);
}
#endif
2015-04-24 17:03:44 +01:00
InitWTime ();
InitRandom ();
/* let the caller control signals as it sees fit */
InitSignals ();
}
2015-04-24 17:03:44 +01:00
void
Yap_InitTime( int wid )
{
InitTime( wid );
}
2015-04-24 17:03:44 +01:00
void
Yap_ReInitWallTime (void)
{
InitWTime();
2015-06-17 23:49:02 +01:00
if (Yap_global->LastWtimePtr_ != NULL)
Yap_FreeCodeSpace(Yap_global->LastWtimePtr_);
2015-04-24 17:03:44 +01:00
InitLastWtime();
}
2015-04-24 17:03:44 +01:00
static Int
p_unix( USES_REGS1 )
{
#ifdef unix
2015-04-24 17:03:44 +01:00
return TRUE;
#else
#ifdef __unix__
2015-04-24 17:03:44 +01:00
return TRUE;
#else
#ifdef __APPLE__
2015-04-24 17:03:44 +01:00
return TRUE;
#else
2015-04-24 17:03:44 +01:00
return FALSE;
#endif
#endif
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
static Int
p_win32( USES_REGS1 )
{
#ifdef _WIN32
2015-04-24 17:03:44 +01:00
return TRUE;
#else
#ifdef __CYGWIN__
2015-04-24 17:03:44 +01:00
return TRUE;
#else
2015-04-24 17:03:44 +01:00
return FALSE;
#endif
#endif
2015-04-24 17:03:44 +01:00
}
2015-04-24 17:03:44 +01:00
static Int
p_enable_interrupts( USES_REGS1 )
{
LOCAL_InterruptsDisabled--;
if (LOCAL_Signals && !LOCAL_InterruptsDisabled) {
CreepFlag = Unsigned(LCL0);
if ( !Yap_only_has_signal( YAP_CREEP_SIGNAL ) )
EventFlag = Unsigned( LCL0 );
}
return TRUE;
}
2015-04-24 17:03:44 +01:00
static Int
p_disable_interrupts( USES_REGS1 )
{
LOCAL_InterruptsDisabled++;
CalculateStackGap( PASS_REGS1 );
return TRUE;
}
2015-04-24 17:03:44 +01:00
static Int
p_ld_path( USES_REGS1 )
{
return Yap_unify(ARG1,MkAtomTerm(Yap_LookupAtom(YAP_LIBDIR)));
}
2015-04-24 17:03:44 +01:00
static Int
p_address_bits( USES_REGS1 )
{
#if SIZEOF_INT_P==4
2015-04-24 17:03:44 +01:00
return Yap_unify(ARG1,MkIntTerm(32));
#else
2015-04-24 17:03:44 +01:00
return Yap_unify(ARG1,MkIntTerm(64));
#endif
2015-04-24 17:03:44 +01:00
}
#ifdef _WIN32
2015-04-24 17:03:44 +01:00
/* This code is from SWI-Prolog by Jan Wielemaker */
#define wstreq(s,q) (wcscmp((s), (q)) == 0)
2015-04-24 17:03:44 +01:00
static HKEY
reg_open_key(const wchar_t *which, int create)
{ HKEY key = HKEY_CURRENT_USER;
DWORD disp;
LONG rval;
while(*which)
{ wchar_t buf[256];
wchar_t *s;
HKEY tmp;
for(s=buf; *which && !(*which == '/' || *which == '\\'); )
*s++ = *which++;
*s = '\0';
if ( *which )
which++;
if ( wstreq(buf, L"HKEY_CLASSES_ROOT") )
{ key = HKEY_CLASSES_ROOT;
continue;
} else if ( wstreq(buf, L"HKEY_CURRENT_USER") )
{ key = HKEY_CURRENT_USER;
continue;
} else if ( wstreq(buf, L"HKEY_LOCAL_MACHINE") )
{ key = HKEY_LOCAL_MACHINE;
continue;
} else if ( wstreq(buf, L"HKEY_USERS") )
{ key = HKEY_USERS;
continue;
}
2015-04-24 17:03:44 +01:00
if ( RegOpenKeyExW(key, buf, 0L, KEY_READ, &tmp) == ERROR_SUCCESS )
{ RegCloseKey(key);
key = tmp;
continue;
}
2015-04-24 17:03:44 +01:00
if ( !create )
return NULL;
rval = RegCreateKeyExW(key, buf, 0, L"", 0,
KEY_ALL_ACCESS, NULL, &tmp, &disp);
RegCloseKey(key);
if ( rval == ERROR_SUCCESS )
key = tmp;
else
return NULL;
}
return key;
}
#define MAXREGSTRLEN 1024
2015-04-24 17:03:44 +01:00
static void
recover_space(wchar_t *k, Atom At)
{
if (At->WStrOfAE != k)
Yap_FreeCodeSpace((char *)k);
}
2015-04-24 17:03:44 +01:00
static wchar_t *
WideStringFromAtom(Atom KeyAt USES_REGS)
{
if (IsWideAtom(KeyAt)) {
return KeyAt->WStrOfAE;
} else {
int len = strlen(KeyAt->StrOfAE);
int sz = sizeof(wchar_t)*(len+1);
char *chp = KeyAt->StrOfAE;
wchar_t *kptr, *k;
k = (wchar_t *)Yap_AllocCodeSpace(sz);
while (k == NULL) {
if (!Yap_growheap(FALSE, sz, NULL)) {
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, MkIntegerTerm(sz), "generating key in win_registry_get_value/3");
2015-04-24 17:03:44 +01:00
return FALSE;
}
2015-01-20 03:00:42 +00:00
}
2015-04-24 17:03:44 +01:00
kptr = k;
while ((*kptr++ = *chp++));
return k;
}
}
2015-04-24 17:03:44 +01:00
static Int
p_win_registry_get_value( USES_REGS1 )
{
DWORD type;
BYTE data[MAXREGSTRLEN];
DWORD len = sizeof(data);
wchar_t *k, *name;
HKEY key;
Term Key = Deref(ARG1);
Term Name = Deref(ARG2);
Atom KeyAt, NameAt;
if (IsVarTerm(Key)) {
Yap_Error(INSTANTIATION_ERROR,Key,"argument to win_registry_get_value unbound");
return FALSE;
}
if (!IsAtomTerm(Key)) {
Yap_Error(TYPE_ERROR_ATOM,Key,"argument to win_registry_get_value");
return FALSE;
}
KeyAt = AtomOfTerm(Key);
if (IsVarTerm(Name)) {
Yap_Error(INSTANTIATION_ERROR,Key,"argument to win_registry_get_value unbound");
return FALSE;
}
if (!IsAtomTerm(Name)) {
Yap_Error(TYPE_ERROR_ATOM,Key,"argument to win_registry_get_value");
return FALSE;
}
NameAt = AtomOfTerm(Name);
2015-04-24 17:03:44 +01:00
k = WideStringFromAtom(KeyAt PASS_REGS);
if ( !(key=reg_open_key(k, FALSE)) ) {
Yap_Error(EXISTENCE_ERROR_KEY, Key, "argument to win_registry_get_value");
recover_space(k, KeyAt);
return FALSE;
}
2015-04-24 17:03:44 +01:00
name = WideStringFromAtom(NameAt PASS_REGS);
if ( RegQueryValueExW(key, name, NULL, &type, data, &len) == ERROR_SUCCESS ) {
RegCloseKey(key);
switch(type) {
case REG_SZ:
recover_space(k, KeyAt);
recover_space(name, NameAt);
((wchar_t *)data)[len] = '\0';
return Yap_unify(MkAtomTerm(Yap_LookupMaybeWideAtom((wchar_t *)data)),ARG3);
case REG_DWORD:
recover_space(k, KeyAt);
recover_space(name, NameAt);
{
DWORD *d = (DWORD *)data;
return Yap_unify(MkIntegerTerm((Int)d[0]),ARG3);
}
default:
recover_space(k, KeyAt);
recover_space(name, NameAt);
return FALSE;
}
}
recover_space(k, KeyAt);
recover_space(name, NameAt);
return FALSE;
}
2015-04-24 17:03:44 +01:00
char *
Yap_RegistryGetString(char *name)
{
DWORD type;
BYTE data[MAXREGSTRLEN];
DWORD len = sizeof(data);
HKEY key;
char *ptr;
int i;
2012-06-21 09:09:49 +01:00
#if SIZEOF_INT_P == 8
2015-04-24 17:03:44 +01:00
if ( !(key=reg_open_key(L"HKEY_LOCAL_MACHINE/SOFTWARE/YAP/Prolog64", FALSE)) ) {
return NULL;
}
2012-06-21 09:09:49 +01:00
#else
2015-04-24 17:03:44 +01:00
if ( !(key=reg_open_key(L"HKEY_LOCAL_MACHINE/SOFTWARE/YAP/Prolog", FALSE)) ) {
return NULL;
}
2012-06-21 09:09:49 +01:00
#endif
2015-04-24 17:03:44 +01:00
if ( RegQueryValueEx(key, name, NULL, &type, data, &len) == ERROR_SUCCESS ) {
RegCloseKey(key);
switch(type) {
case REG_SZ:
ptr = malloc(len+2);
if (!ptr)
return NULL;
for (i=0; i<= len; i++)
ptr[i] = data[i];
ptr[len+1] = '\0';
return ptr;
default:
return NULL;
2015-04-24 17:03:44 +01:00
}
}
2015-04-24 17:03:44 +01:00
return NULL;
}
#endif
2015-04-24 17:03:44 +01:00
void
Yap_InitSysPreds(void)
{
CACHE_REGS
Term cm = CurrentModule;
2015-04-24 17:03:44 +01:00
/* can only do after heap is initialised */
InitLastWtime();
2015-06-17 23:49:02 +01:00
Yap_InitCPred ("srandom", 1, Srandom, SafePredFlag);
2014-05-28 01:12:51 +01:00
#if HAVE_RANDOM
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("init_random_state", 3, p_init_random_state, SafePredFlag);
Yap_InitCPred ("set_random_state", 2, p_set_random_state, SafePredFlag);
Yap_InitCPred ("release_random_state", 1, p_release_random_state, SafePredFlag);
#endif
2015-06-17 23:49:02 +01:00
Yap_InitCPred ("$absolute_file_name", 2, absolute_file_name, SafePredFlag|SyncPredFlag);
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("log_event", 1, p_log_event, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("sh", 0, p_sh, SafePredFlag|SyncPredFlag);
2015-06-17 23:49:02 +01:00
Yap_InitCPred ("$shell", 1, p_shell, SafePredFlag|SyncPredFlag);
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("system", 1, p_system, SafePredFlag|SyncPredFlag|UserCPredFlag);
Yap_InitCPred ("rename", 2, p_mv, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("$yap_home", 1, p_yap_home, SafePredFlag);
Yap_InitCPred ("$yap_paths", 3, p_yap_paths, SafePredFlag);
Yap_InitCPred ("$dir_separator", 1, p_dir_sp, SafePredFlag);
2015-06-17 23:49:02 +01:00
Yap_InitCPred ("libraries_directories",2, libraries_directories, 0);
Yap_InitCPred ("system_library", 1, system_library, 0);
Yap_InitCPred ("commons_library", 1, commons_library, 0);
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("$alarm", 4, p_alarm, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("$getenv", 2, p_getenv, SafePredFlag);
Yap_InitCPred ("$putenv", 2, p_putenv, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("$host_type", 1, p_host_type, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("$env_separator", 1, p_env_separator, SafePredFlag);
Yap_InitCPred ("$unix", 0, p_unix, SafePredFlag);
Yap_InitCPred ("$win32", 0, p_win32, SafePredFlag);
Yap_InitCPred ("$ld_path", 1, p_ld_path, SafePredFlag);
Yap_InitCPred ("$address_bits", 1, p_address_bits, SafePredFlag);
Yap_InitCPred ("$expand_file_name", 2, p_expand_file_name, SyncPredFlag);
2015-06-17 23:49:02 +01:00
Yap_InitCPred ("working_directory", 2,working_directory, SyncPredFlag);
Yap_InitCPred ("prolog_to_os_filename", 2, prolog_to_os_filename, SyncPredFlag);
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("$fpe_error", 0, p_fpe_error, 0);
#ifdef _WIN32
2015-04-24 17:03:44 +01:00
Yap_InitCPred ("win_registry_get_value", 3, p_win_registry_get_value,0);
#endif
2015-04-24 17:03:44 +01:00
CurrentModule = HACKS_MODULE;
Yap_InitCPred ("virtual_alarm", 4, p_virtual_alarm, SafePredFlag|SyncPredFlag);
Yap_InitCPred ("enable_interrupts", 0, p_enable_interrupts, SafePredFlag);
Yap_InitCPred ("disable_interrupts", 0, p_disable_interrupts, SafePredFlag);
CurrentModule = OPERATING_SYSTEM_MODULE;
Yap_InitCPred ("true_file_name", 2, p_true_file_name, SyncPredFlag);
Yap_InitCPred ("true_file_name", 3, p_true_file_name3, SyncPredFlag);
2015-07-06 12:03:16 +01:00
Yap_InitCPred ("rmdir", 2, p_rmdir, SyncPredFlag);
2015-04-24 17:03:44 +01:00
CurrentModule = cm;
2015-07-06 12:03:16 +01:00
Yap_InitCPred ("make_directory", 1, make_directory, SyncPredFlag);
2015-04-24 17:03:44 +01:00
}
#ifdef VAX
2015-04-24 17:03:44 +01:00
/* avoid longjmp botch */
2015-04-24 17:03:44 +01:00
int vax_absmi_fp;
2015-04-24 17:03:44 +01:00
typedef struct
{
int eh;
int flgs;
int ap;
int fp;
int pc;
int dummy1;
int dummy2;
int dummy3;
int oldfp;
int dummy4;
int dummy5;
int dummy6;
int oldpc;
}
2015-04-24 17:03:44 +01:00
*VaxFramePtr;
2015-04-24 17:03:44 +01:00
VaxFixFrame (dummy)
{
int maxframes = 100;
VaxFramePtr fp = (VaxFramePtr) (((int *) &dummy) - 6);
while (--maxframes)
{
fp = (VaxFramePtr) fp->fp;
if (fp->flgs == 0)
{
if (fp->oldfp >= &REGS[6] && fp->oldfp < &REGS[REG_SIZE])
fp->oldfp = vax_absmi_fp;
return;
}
}
}
#endif
#if defined(_WIN32)
#include <windows.h>
2015-04-24 17:03:44 +01:00
int WINAPI win_yap(HANDLE, DWORD, LPVOID);
2015-04-24 17:03:44 +01:00
int WINAPI win_yap(HANDLE hinst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return 1;
}
#endif
#if (defined(YAPOR) || defined(THREADS)) && !defined(USE_PTHREAD_LOCKING)
#ifdef sparc
2015-04-24 17:03:44 +01:00
void rw_lock_voodoo(void);
void
rw_lock_voodoo(void) {
/* code taken from the Linux kernel, it handles shifting between locks */
/* Read/writer locks, as usual this is overly clever to make it as fast as possible. */
/* caches... */
__asm__ __volatile__(
"___rw_read_enter_spin_on_wlock:\n"
" orcc %g2, 0x0, %g0\n"
" be,a ___rw_read_enter\n"
" ldstub [%g1 + 3], %g2\n"
" b ___rw_read_enter_spin_on_wlock\n"
" ldub [%g1 + 3], %g2\n"
"___rw_read_exit_spin_on_wlock:\n"
" orcc %g2, 0x0, %g0\n"
" be,a ___rw_read_exit\n"
" ldstub [%g1 + 3], %g2\n"
" b ___rw_read_exit_spin_on_wlock\n"
" ldub [%g1 + 3], %g2\n"
"___rw_write_enter_spin_on_wlock:\n"
" orcc %g2, 0x0, %g0\n"
" be,a ___rw_write_enter\n"
" ldstub [%g1 + 3], %g2\n"
" b ___rw_write_enter_spin_on_wlock\n"
" ld [%g1], %g2\n"
"\n"
" .globl ___rw_read_enter\n"
"___rw_read_enter:\n"
" orcc %g2, 0x0, %g0\n"
" bne,a ___rw_read_enter_spin_on_wlock\n"
" ldub [%g1 + 3], %g2\n"
" ld [%g1], %g2\n"
" add %g2, 1, %g2\n"
" st %g2, [%g1]\n"
" retl\n"
" mov %g4, %o7\n"
" .globl ___rw_read_exit\n"
"___rw_read_exit:\n"
" orcc %g2, 0x0, %g0\n"
" bne,a ___rw_read_exit_spin_on_wlock\n"
" ldub [%g1 + 3], %g2\n"
" ld [%g1], %g2\n"
" sub %g2, 0x1ff, %g2\n"
" st %g2, [%g1]\n"
" retl\n"
" mov %g4, %o7\n"
" .globl ___rw_write_enter\n"
"___rw_write_enter:\n"
" orcc %g2, 0x0, %g0\n"
" bne ___rw_write_enter_spin_on_wlock\n"
" ld [%g1], %g2\n"
" andncc %g2, 0xff, %g0\n"
" bne,a ___rw_write_enter_spin_on_wlock\n"
" stb %g0, [%g1 + 3]\n"
" retl\n"
" mov %g4, %o7\n"
);
}
#endif /* sparc */
#endif /* YAPOR || THREADS */
2015-01-04 23:58:23 +00:00
2015-04-24 17:03:44 +01:00
//@