SWI update

This commit is contained in:
Vítor Santos Costa 2013-01-16 11:28:58 +00:00
parent 0eacb68907
commit abe6621495
11 changed files with 711 additions and 445 deletions

View File

@ -476,14 +476,11 @@ int raiseStackOverflow(int overflow)
* FEATURES * * FEATURES *
*******************************/ *******************************/
int
PL_set_prolog_flag(const char *name, int type, ...) PL_set_prolog_flag(const char *name, int type, ...)
{ va_list args; { va_list args;
int rval = TRUE; int rval = TRUE;
int flags = (type & FF_MASK); int flags = (type & FF_MASK);
initPrologFlagTable();
va_start(args, type); va_start(args, type);
switch(type & ~FF_MASK) switch(type & ~FF_MASK)
{ case PL_BOOL: { case PL_BOOL:
@ -494,10 +491,8 @@ PL_set_prolog_flag(const char *name, int type, ...)
} }
case PL_ATOM: case PL_ATOM:
{ const char *v = va_arg(args, const char *); { const char *v = va_arg(args, const char *);
#ifndef __YAP_PROLOG__ // VSC if ( !GD->initialised )
if ( !GD->initialised ) // VSC initAtoms();
initAtoms();
#endif
setPrologFlag(name, FT_ATOM|flags, v); setPrologFlag(name, FT_ATOM|flags, v);
break; break;
} }
@ -509,13 +504,12 @@ PL_set_prolog_flag(const char *name, int type, ...)
default: default:
rval = FALSE; rval = FALSE;
} }
va_end(args); va_end(args);
return rval; return rval;
} }
int int
PL_unify_chars(term_t t, int flags, size_t len, const char *s) PL_unify_chars(term_t t, int flags, size_t len, const char *s)
{ PL_chars_t text; { PL_chars_t text;
@ -761,6 +755,12 @@ PL_get_list_nchars(term_t l, size_t *length, char **s, unsigned int flags)
fail; fail;
} }
void *
PL_malloc_uncollectable(size_t sz)
{
return malloc(sz);
}
int int
PL_get_list_chars(term_t l, char **s, unsigned flags) PL_get_list_chars(term_t l, char **s, unsigned flags)
{ return PL_get_list_nchars(l, NULL, s, flags); { return PL_get_list_nchars(l, NULL, s, flags);

View File

@ -468,9 +468,6 @@ typedef struct
#define FT_FROM_VALUE 0x0f /* Determine type from value */ #define FT_FROM_VALUE 0x0f /* Determine type from value */
#define FT_MASK 0x0f /* mask to get type */ #define FT_MASK 0x0f /* mask to get type */
#define FF_READONLY 0x10 /* feature is read-only */
#define FF_KEEP 0x20 /* keep value it already set */
#define PLFLAG_CHARESCAPE 0x000001 /* handle \ in atoms */ #define PLFLAG_CHARESCAPE 0x000001 /* handle \ in atoms */
#define PLFLAG_GC 0x000002 /* do GC */ #define PLFLAG_GC 0x000002 /* do GC */
#define PLFLAG_TRACE_GC 0x000004 /* verbose gc */ #define PLFLAG_TRACE_GC 0x000004 /* verbose gc */
@ -540,6 +537,7 @@ typedef enum
#define SYSTEM_MODE (LD->prolog_flag.access_level == ACCESS_LEVEL_SYSTEM) #define SYSTEM_MODE (LD->prolog_flag.access_level == ACCESS_LEVEL_SYSTEM)
#define PL_malloc_atomic malloc
/* vsc: global variables */ /* vsc: global variables */
#include "pl-global.h" #include "pl-global.h"
@ -702,6 +700,7 @@ extern int PL_unify_atomic(term_t t, PL_atomic_t a);
extern int _PL_unify_atomic(term_t t, PL_atomic_t a); extern int _PL_unify_atomic(term_t t, PL_atomic_t a);
extern int _PL_unify_string(term_t t, word w); extern int _PL_unify_string(term_t t, word w);
#define _PL_get_arg(X,Y,Z) PL_get_arg(X,Y,Z) #define _PL_get_arg(X,Y,Z) PL_get_arg(X,Y,Z)
extern IOSTREAM ** /* provide access to Suser_input, */ extern IOSTREAM ** /* provide access to Suser_input, */
@ -911,7 +910,7 @@ COMMON(Buffer) codes_or_chars_to_buffer(term_t l, unsigned int flags,
COMMON(bool) systemMode(bool accept); COMMON(bool) systemMode(bool accept);
COMMON(void) initPrologFlagTable(void); COMMON(void) cleanupPrologFlags(void);
COMMON(void) initPrologFlags(void); COMMON(void) initPrologFlags(void);
COMMON(int) raiseStackOverflow(int overflow); COMMON(int) raiseStackOverflow(int overflow);

View File

@ -65,6 +65,10 @@ typedef intptr_t ssize_t; /* signed version of size_t */
extern "C" { extern "C" {
#endif #endif
#ifndef PL_HAVE_TERM_T
#define PL_HAVE_TERM_T
typedef uintptr_t term_t;
#endif
/******************************* /*******************************
* CONSTANTS * * CONSTANTS *
*******************************/ *******************************/
@ -335,14 +339,10 @@ PL_EXPORT(int) Sfpasteof(IOSTREAM *s);
PL_EXPORT(int) Sferror(IOSTREAM *s); PL_EXPORT(int) Sferror(IOSTREAM *s);
PL_EXPORT(void) Sclearerr(IOSTREAM *s); PL_EXPORT(void) Sclearerr(IOSTREAM *s);
PL_EXPORT(void) Sseterr(IOSTREAM *s, int which, const char *message); PL_EXPORT(void) Sseterr(IOSTREAM *s, int which, const char *message);
#ifdef _FLI_H_INCLUDED
PL_EXPORT(void) Sset_exception(IOSTREAM *s, term_t ex); PL_EXPORT(void) Sset_exception(IOSTREAM *s, term_t ex);
#else
PL_EXPORT(void) Sset_exception(IOSTREAM *s, intptr_t ex);
#endif
PL_EXPORT(int) Ssetenc(IOSTREAM *s, IOENC new_enc, IOENC *old_enc); PL_EXPORT(int) Ssetenc(IOSTREAM *s, IOENC new_enc, IOENC *old_enc);
PL_EXPORT(int) Sflush(IOSTREAM *s); PL_EXPORT(int) Sflush(IOSTREAM *s);
PL_EXPORT(long) Ssize(IOSTREAM *s); PL_EXPORT(int64_t) Ssize(IOSTREAM *s);
PL_EXPORT(int) Sseek(IOSTREAM *s, long pos, int whence); PL_EXPORT(int) Sseek(IOSTREAM *s, long pos, int whence);
PL_EXPORT(long) Stell(IOSTREAM *s); PL_EXPORT(long) Stell(IOSTREAM *s);
PL_EXPORT(int) Sclose(IOSTREAM *s); PL_EXPORT(int) Sclose(IOSTREAM *s);

View File

@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -189,7 +189,8 @@ outtext(format_state *state, PL_chars_t *txt)
#define format_predicates (GD->format.predicates) #define format_predicates (GD->format.predicates)
static int update_column(int, Char); static int update_column(int, Char);
static bool do_format(IOSTREAM *fd, PL_chars_t *fmt, int ac, term_t av); static bool do_format(IOSTREAM *fd, PL_chars_t *fmt,
int ac, term_t av, Module m);
static void distribute_rubber(struct rubber *, int, int); static void distribute_rubber(struct rubber *, int, int);
static int emit_rubber(format_state *state); static int emit_rubber(format_state *state);
@ -272,7 +273,7 @@ pl_current_format_predicate(term_t chr, term_t descr, control_t h)
static word static word
format_impl(IOSTREAM *out, term_t format, term_t Args) format_impl(IOSTREAM *out, term_t format, term_t Args, Module m)
{ GET_LD { GET_LD
term_t argv; term_t argv;
int argc = 0; int argc = 0;
@ -307,7 +308,7 @@ format_impl(IOSTREAM *out, term_t format, term_t Args)
break; break;
} }
rval = do_format(out, &fmt, argc, argv); rval = do_format(out, &fmt, argc, argv, m);
PL_free_text(&fmt); PL_free_text(&fmt);
if ( !endCritical ) if ( !endCritical )
return FALSE; return FALSE;
@ -318,32 +319,21 @@ format_impl(IOSTREAM *out, term_t format, term_t Args)
word word
pl_format3(term_t out, term_t format, term_t args) pl_format3(term_t out, term_t format, term_t args)
{ redir_context ctx; { GET_LD
redir_context ctx;
word rc; word rc;
#if __YAP_PROLOG__ Module m = NULL;
/* term_t list = PL_new_term_ref();
YAP allows the last argument to format to be of the form
module:[]
*/
YAP_Term mod;
#endif
if ( (rc=setupOutputRedirect(out, &ctx, FALSE)) ) { if ( !PL_strip_module(args, &m, list) )
#if __YAP_PROLOG__ return FALSE;
/* module processing */
{ if ( (rc=setupOutputRedirect(out, &ctx, FALSE)) )
args = Yap_fetch_module_for_format(args, &mod); { if ( (rc = format_impl(ctx.stream, format, list, m)) )
}
#endif
{ if ( (rc = format_impl(ctx.stream, format, args)) )
rc = closeOutputRedirect(&ctx); rc = closeOutputRedirect(&ctx);
else else
discardOutputRedirect(&ctx); discardOutputRedirect(&ctx);
} }
#if __YAP_PROLOG__
YAP_SetCurrentModule(mod);
#endif
}
return rc; return rc;
} }
@ -374,7 +364,7 @@ get_chr_from_text(const PL_chars_t *t, int index)
********************************/ ********************************/
static bool static bool
do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv) do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv, Module m)
{ GET_LD { GET_LD
format_state state; /* complete state */ format_state state; /* complete state */
int tab_stop = 0; /* padded tab stop */ int tab_stop = 0; /* padded tab stop */
@ -443,7 +433,7 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
char buf[BUFSIZE]; char buf[BUFSIZE];
char *str = buf; char *str = buf;
size_t bufsize = BUFSIZE; size_t bufsize = BUFSIZE;
unsigned int i; int i;
PL_predicate_info(proc, NULL, &arity, NULL); PL_predicate_info(proc, NULL, &arity, NULL);
av = PL_new_term_refs(arity); av = PL_new_term_refs(arity);
@ -481,7 +471,9 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
if ( !PL_get_text(argv, &txt, CVT_ATOMIC) ) if ( !PL_get_text(argv, &txt, CVT_ATOMIC) )
FMT_ARG("a", argv); FMT_ARG("a", argv);
SHIFT; SHIFT;
outtext(&state, &txt); rc = outtext(&state, &txt);
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -494,7 +486,9 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
SHIFT; SHIFT;
while(times-- > 0) while(times-- > 0)
{ outchr(&state, chr); { rc = outchr(&state, chr);
if ( !rc )
goto out;
} }
} else } else
FMT_ARG("c", argv); FMT_ARG("c", argv);
@ -525,8 +519,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
initBuffer(&u.b); initBuffer(&u.b);
formatFloat(c, arg, &n, &u.b1); formatFloat(c, arg, &n, &u.b1);
clearNumber(&n); clearNumber(&n);
outstring0(&state, baseBuffer(&u.b, char)); rc = outstring0(&state, baseBuffer(&u.b, char));
discardBuffer(&u.b); discardBuffer(&u.b);
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -564,8 +560,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
formatNumber(FALSE, 0, arg, c == 'r', &i, (Buffer)&b); formatNumber(FALSE, 0, arg, c == 'r', &i, (Buffer)&b);
} }
clearNumber(&i); clearNumber(&i);
outstring0(&state, baseBuffer(&b, char)); rc = outstring0(&state, baseBuffer(&b, char));
discardBuffer(&b); discardBuffer(&b);
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -576,8 +574,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
if ( !PL_get_text(argv, &txt, CVT_LIST|CVT_STRING) && if ( !PL_get_text(argv, &txt, CVT_LIST|CVT_STRING) &&
!PL_get_text(argv, &txt, CVT_ATOM) ) /* SICStus compat */ !PL_get_text(argv, &txt, CVT_ATOM) ) /* SICStus compat */
FMT_ARG("s", argv); FMT_ARG("s", argv);
outtext(&state, &txt); rc = outtext(&state, &txt);
SHIFT; SHIFT;
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -610,8 +610,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
str = buf; str = buf;
tellString(&str, &bufsize, ENC_UTF8); tellString(&str, &bufsize, ENC_UTF8);
(*f)(argv); rc = (*f)(argv);
toldString(); toldString();
if ( !rc )
goto out;
oututf8(&state, str, bufsize); oututf8(&state, str, bufsize);
if ( str != buf ) if ( str != buf )
free(str); free(str);
@ -632,8 +634,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
str = buf; str = buf;
tellString(&str, &bufsize, ENC_UTF8); tellString(&str, &bufsize, ENC_UTF8);
(*f)(argv); rc = (*f)(argv);
toldString(); toldString();
if ( !rc )
goto out;
oututf8(&state, str, bufsize); oututf8(&state, str, bufsize);
if ( str != buf ) if ( str != buf )
free(str); free(str);
@ -704,7 +708,7 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
{ FMT_ERROR("not enough arguments"); { FMT_ERROR("not enough arguments");
} }
tellString(&str, &bufsize, ENC_UTF8); tellString(&str, &bufsize, ENC_UTF8);
rval = callProlog(NULL, argv, PL_Q_CATCH_EXCEPTION, &ex); rval = callProlog(m, argv, PL_Q_CATCH_EXCEPTION, &ex);
toldString(); toldString();
oututf8(&state, str, bufsize); oututf8(&state, str, bufsize);
if ( str != buf ) if ( str != buf )
@ -724,7 +728,9 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
break; break;
} }
case '~': /* ~ */ case '~': /* ~ */
{ outchr(&state, '~'); { rc = outchr(&state, '~');
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -735,7 +741,10 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
if ( c == 'N' && state.column == 0 ) if ( c == 'N' && state.column == 0 )
arg--; arg--;
while( arg-- > 0 ) while( arg-- > 0 )
outchr(&state, '\n'); { rc = outchr(&state, '\n');
if ( !rc )
goto out;
}
here++; here++;
break; break;
} }
@ -790,7 +799,9 @@ do_format(IOSTREAM *fd, PL_chars_t *fmt, int argc, term_t argv)
break; /* the '~' switch */ break; /* the '~' switch */
} }
default: default:
{ outchr(&state, c); { rc = outchr(&state, c);
if ( !rc )
goto out;
here++; here++;
break; break;
} }
@ -1032,7 +1043,8 @@ formatFloat(int how, int arg, Number f, Buffer out)
while(written >= size) while(written >= size)
{ size = written+1; { size = written+1;
growBuffer(out, size); /* reserve for -.e<null> */ if ( !growBuffer(out, size) ) /* reserve for -.e<null> */
outOfCore();
written = gmp_snprintf(baseBuffer(out, char), size, tmp, mpf); written = gmp_snprintf(baseBuffer(out, char), size, tmp, mpf);
} }
mpf_clear(mpf); mpf_clear(mpf);
@ -1053,7 +1065,8 @@ formatFloat(int how, int arg, Number f, Buffer out)
while(written >= size) while(written >= size)
{ size = written+1; { size = written+1;
growBuffer(out, size); if ( !growBuffer(out, size) )
outOfCore();
written = snprintf(baseBuffer(out, char), size, tmp, f->value.f); written = snprintf(baseBuffer(out, char), size, tmp, f->value.f);
} }
out->top = out->base + written; out->top = out->base + written;

View File

@ -3,9 +3,10 @@
Part of SWI-Prolog Part of SWI-Prolog
Author: Jan Wielemaker Author: Jan Wielemaker
E-mail: jan@swi.psy.uva.nl E-mail: J.Wielemaker@cs.vu.nl
WWW: http://www.swi-prolog.org WWW: http://www.swi-prolog.org
Copyright (C): 1985-2002, University of Amsterdam Copyright (C): 1985-2011, University of Amsterdam
VU University Amsterdam
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -19,7 +20,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "pl-incl.h" #include "pl-incl.h"
@ -29,9 +30,9 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef __WATCOMC__ #ifdef O_XOS
#include <direct.h> # include "windows/dirent.h"
#else /*__WATCOMC__*/ #else
#if HAVE_DIRENT_H #if HAVE_DIRENT_H
# include <dirent.h> # include <dirent.h>
#else #else
@ -46,7 +47,7 @@
# include <ndir.h> # include <ndir.h>
# endif # endif
#endif #endif
#endif /*__WATCOMC__*/ #endif /*O_XOS*/
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> #include <sys/stat.h>
@ -326,8 +327,8 @@ PRED_IMPL("wildcard_match", 2, wildcard_match, 0)
{ char *p, *s; { char *p, *s;
compiled_pattern buf; compiled_pattern buf;
if ( !PL_get_chars_ex(A1, &p, CVT_ALL) || if ( !PL_get_chars(A1, &p, CVT_ALL|CVT_EXCEPTION) ||
!PL_get_chars_ex(A2, &s, CVT_ALL) ) !PL_get_chars(A2, &s, CVT_ALL|CVT_EXCEPTION) )
fail; fail;
if ( compilePattern(p, &buf) ) if ( compilePattern(p, &buf) )
@ -423,6 +424,7 @@ expand(const char *pattern, GlobInfo info)
compiled_pattern cbuf; compiled_pattern cbuf;
char prefix[MAXPATHLEN]; /* before first pattern */ char prefix[MAXPATHLEN]; /* before first pattern */
char patbuf[MAXPATHLEN]; /* pattern buffer */ char patbuf[MAXPATHLEN]; /* pattern buffer */
size_t prefix_len;
int end, dot; int end, dot;
initBuffer(&info->files); initBuffer(&info->files);
@ -441,15 +443,19 @@ expand(const char *pattern, GlobInfo info)
switch( (c=*s++) ) switch( (c=*s++) )
{ case EOS: { case EOS:
if ( s > pat ) /* something left and expanded */ if ( s > pat ) /* something left and expanded */
{ un_escape(prefix, pat, s); { size_t prefix_len;
un_escape(prefix, pat, s);
prefix_len = strlen(prefix);
end = info->end; end = info->end;
for( ; info->start < end; info->start++ ) for( ; info->start < end; info->start++ )
{ char path[MAXPATHLEN]; { char path[MAXPATHLEN];
size_t plen; const char *entry = expand_entry(info, info->start);
size_t plen = strlen(entry);
strcpy(path, expand_entry(info, info->start)); if ( plen+prefix_len+2 <= MAXPATHLEN )
plen = strlen(path); { strcpy(path, entry);
if ( prefix[0] && plen > 0 && path[plen-1] != '/' ) if ( prefix[0] && plen > 0 && path[plen-1] != '/' )
path[plen++] = '/'; path[plen++] = '/';
strcpy(&path[plen], prefix); strcpy(&path[plen], prefix);
@ -457,6 +463,7 @@ expand(const char *pattern, GlobInfo info)
add_path(path, info); add_path(path, info);
} }
} }
}
succeed; succeed;
case '[': /* meta characters: expand */ case '[': /* meta characters: expand */
case '{': case '{':
@ -489,6 +496,7 @@ expand(const char *pattern, GlobInfo info)
*/ */
un_escape(prefix, pat, head); un_escape(prefix, pat, head);
un_escape(patbuf, head, tail); un_escape(patbuf, head, tail);
prefix_len = strlen(prefix);
if ( !compilePattern(patbuf, &cbuf) ) /* syntax error */ if ( !compilePattern(patbuf, &cbuf) ) /* syntax error */
fail; fail;
@ -502,6 +510,10 @@ expand(const char *pattern, GlobInfo info)
char path[MAXPATHLEN]; char path[MAXPATHLEN];
char tmp[MAXPATHLEN]; char tmp[MAXPATHLEN];
const char *current = expand_entry(info, info->start); const char *current = expand_entry(info, info->start);
size_t clen = strlen(current);
if ( clen+prefix_len+1 > sizeof(path) )
continue;
strcpy(path, current); strcpy(path, current);
strcat(path, prefix); strcat(path, prefix);
@ -521,14 +533,13 @@ expand(const char *pattern, GlobInfo info)
matchPattern(e->d_name, &cbuf) ) matchPattern(e->d_name, &cbuf) )
{ char newp[MAXPATHLEN]; { char newp[MAXPATHLEN];
strcpy(newp, path); if ( plen+strlen(e->d_name)+1 < sizeof(newp) )
{ strcpy(newp, path);
strcpy(&newp[plen], e->d_name); strcpy(&newp[plen], e->d_name);
/* if ( !tail[0] || ExistsDirectory(newp) )
Saves memory, but involves one more file-access
*/
add_path(newp, info); add_path(newp, info);
} }
} }
}
closedir(d); closedir(d);
} }
} }
@ -579,11 +590,11 @@ PRED_IMPL("expand_file_name", 2, expand_file_name, 0)
term_t head = PL_new_term_ref(); term_t head = PL_new_term_ref();
int i; int i;
if ( !PL_get_chars_ex(A1, &s, CVT_ALL|REP_FN) ) if ( !PL_get_chars(A1, &s, CVT_ALL|REP_FN|CVT_EXCEPTION) )
fail; fail;
if ( strlen(s) > sizeof(spec)-1 ) if ( strlen(s) > sizeof(spec)-1 )
return PL_error(NULL, 0, "File name too intptr_t", return PL_error(NULL, 0, NULL, ERR_REPRESENTATION,
ERR_DOMAIN, ATOM_pattern, A1); ATOM_max_path_length);
if ( !expandVars(s, spec, sizeof(spec)) ) if ( !expandVars(s, spec, sizeof(spec)) )
fail; fail;

View File

@ -1,11 +1,10 @@
/* $Id$ /* Part of SWI-Prolog
Part of SWI-Prolog
Author: Jan Wielemaker Author: Jan Wielemaker
E-mail: J.wielemaker@uva.nl E-mail: J.wielemaker@vu.nl
WWW: http://www.swi-prolog.org WWW: http://www.swi-prolog.org
Copyright (C): 1985-2008, University of Amsterdam Copyright (C): 1985-2012, University of Amsterdam
VU University Amsterdam
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -19,7 +18,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/*#define O_DEBUG 1*/ /*#define O_DEBUG 1*/
@ -80,6 +79,8 @@ static void setTZPrologFlag(void);
static void setVersionPrologFlag(void); static void setVersionPrologFlag(void);
#endif #endif
static atom_t lookupAtomFlag(atom_t key); static atom_t lookupAtomFlag(atom_t key);
static void initPrologFlagTable(void);
typedef struct _prolog_flag typedef struct _prolog_flag
{ short flags; /* Type | Flags */ { short flags; /* Type | Flags */
@ -138,7 +139,7 @@ setPrologFlag(const char *name, int flags, ...)
if ( flags & FF_KEEP ) if ( flags & FF_KEEP )
return; return;
} else } else
{ f = allocHeap(sizeof(*f)); { f = allocHeapOrHalt(sizeof(*f));
f->index = -1; f->index = -1;
f->flags = flags; f->flags = flags;
addHTable(GD->prolog_flag.table, (void *)an, f); addHTable(GD->prolog_flag.table, (void *)an, f);
@ -155,7 +156,8 @@ setPrologFlag(const char *name, int flags, ...)
val = (f->value.a == ATOM_true); val = (f->value.a == ATOM_true);
} else if ( !s ) /* 1st definition */ } else if ( !s ) /* 1st definition */
{ f->index = indexOfBoolMask(mask); { f->index = indexOfBoolMask(mask);
DEBUG(2, Sdprintf("Prolog flag %s at 0x%08lx\n", name, mask)); DEBUG(MSG_PROLOG_FLAG,
Sdprintf("Prolog flag %s at 0x%08lx\n", name, mask));
} }
f->value.a = (val ? ATOM_true : ATOM_false); f->value.a = (val ? ATOM_true : ATOM_false);
@ -211,12 +213,20 @@ setPrologFlag(const char *name, int flags, ...)
} }
static void
freePrologFlag(prolog_flag *f)
{ if ( (f->flags & FT_MASK) == FT_TERM )
PL_erase(f->value.t);
freeHeap(f, sizeof(*f));
}
#ifdef O_PLMT #ifdef O_PLMT
static void static void
copySymbolPrologFlagTable(Symbol s) copySymbolPrologFlagTable(Symbol s)
{ GET_LD { prolog_flag *f = s->value;
prolog_flag *f = s->value; prolog_flag *copy = allocHeapOrHalt(sizeof(*copy));
prolog_flag *copy = allocHeap(sizeof(*copy));
*copy = *f; *copy = *f;
if ( (f->flags & FT_MASK) == FT_TERM ) if ( (f->flags & FT_MASK) == FT_TERM )
@ -227,13 +237,7 @@ copySymbolPrologFlagTable(Symbol s)
static void static void
freeSymbolPrologFlagTable(Symbol s) freeSymbolPrologFlagTable(Symbol s)
{ GET_LD { freePrologFlag(s->value);
prolog_flag *f = s->value;
if ( (f->flags & FT_MASK) == FT_TERM )
PL_erase(f->value.t);
freeHeap(f, sizeof(*f));
} }
#endif #endif
@ -267,25 +271,34 @@ setDoubleQuotes(atom_t a, unsigned int *flagp)
static int static int
setUnknown(atom_t a, unsigned int *flagp) setUnknown(term_t value, atom_t a, Module m)
{ unsigned int flags; { unsigned int flags = m->flags & ~(UNKNOWN_MASK);
if ( a == ATOM_error ) if ( a == ATOM_error )
flags = UNKNOWN_ERROR; flags |= UNKNOWN_ERROR;
else if ( a == ATOM_warning ) else if ( a == ATOM_warning )
flags = UNKNOWN_WARNING; flags |= UNKNOWN_WARNING;
else if ( a == ATOM_fail ) else if ( a == ATOM_fail )
flags = UNKNOWN_FAIL; flags |= UNKNOWN_FAIL;
else else
{ GET_LD
term_t value = PL_new_term_ref();
PL_put_atom(value, a);
return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_unknown, value); return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_unknown, value);
if ( !(flags&UNKNOWN_ERROR) && (m == MODULE_user || m == MODULE_system) )
{ GET_LD
if ( m == MODULE_system && !SYSTEM_MODE )
{ term_t key = PL_new_term_ref();
PL_put_atom(key, ATOM_unknown);
return PL_error(NULL, 0, NULL, ERR_PERMISSION,
ATOM_modify, ATOM_flag, key);
} }
*flagp &= ~(UNKNOWN_MASK); if ( !SYSTEM_MODE )
*flagp |= flags; printMessage(ATOM_warning, PL_CHARS, "unknown_in_module_user");
}
m->flags = flags;
succeed; succeed;
} }
@ -308,6 +321,21 @@ setWriteAttributes(atom_t a)
} }
static int
setAccessLevelFromAtom(atom_t a)
{ GET_LD
if ( getAccessLevelMask(a, &LD->prolog_flag.access_level) )
{ succeed;
} else
{ term_t value = PL_new_term_ref();
PL_put_atom(value, a);
return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_access_level, value);
}
}
static int static int
getOccursCheckMask(atom_t a, occurs_check_t *val) getOccursCheckMask(atom_t a, occurs_check_t *val)
{ if ( a == ATOM_false ) { if ( a == ATOM_false )
@ -357,6 +385,30 @@ setEncoding(atom_t a)
} }
static int
setStreamTypeCheck(atom_t a)
{ GET_LD
st_check check;
if ( a == ATOM_false )
check = ST_FALSE;
else if ( a == ATOM_loose )
check = ST_LOOSE;
else if ( a == ATOM_true )
check = ST_TRUE;
else
{ term_t value = PL_new_term_ref();
PL_put_atom(value, a);
return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_stream_type_check, value);
}
LD->IO.stream_type_check = check;
return TRUE;
}
static word static word
set_prolog_flag_unlocked(term_t key, term_t value, int flags) set_prolog_flag_unlocked(term_t key, term_t value, int flags)
{ GET_LD { GET_LD
@ -385,7 +437,7 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
#ifdef O_PLMT #ifdef O_PLMT
if ( GD->statistics.threads_created > 1 ) if ( GD->statistics.threads_created > 1 )
{ prolog_flag *f2 = allocHeap(sizeof(*f2)); { prolog_flag *f2 = allocHeapOrHalt(sizeof(*f2));
*f2 = *f; *f2 = *f;
if ( (f2->flags & FT_MASK) == FT_TERM ) if ( (f2->flags & FT_MASK) == FT_TERM )
@ -399,7 +451,8 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
} }
addHTable(LD->prolog_flag.table, (void *)k, f2); addHTable(LD->prolog_flag.table, (void *)k, f2);
DEBUG(1, Sdprintf("Localised Prolog flag %s\n", PL_atom_chars(k))); DEBUG(MSG_PROLOG_FLAG,
Sdprintf("Localised Prolog flag %s\n", PL_atom_chars(k)));
f = f2; f = f2;
} }
#endif #endif
@ -411,7 +464,7 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
anyway: anyway:
PL_register_atom(k); PL_register_atom(k);
f = allocHeap(sizeof(*f)); f = allocHeapOrHalt(sizeof(*f));
f->index = -1; f->index = -1;
switch( (flags & FT_MASK) ) switch( (flags & FT_MASK) )
@ -437,8 +490,9 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
goto wrong_type; goto wrong_type;
} }
if ( !(f->value.t = PL_record(value)) ) if ( !(f->value.t = PL_record(value)) )
goto wrong_type; { freeHeap(f, sizeof(*f));
f->value.t = PL_record(value); return FALSE;
}
} }
break; break;
} }
@ -483,7 +537,10 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
if ( (flags & FF_READONLY) ) if ( (flags & FF_READONLY) )
f->flags |= FF_READONLY; f->flags |= FF_READONLY;
addHTable(GD->prolog_flag.table, (void *)k, f); if ( !addHTable(GD->prolog_flag.table, (void *)k, f) )
{ freePrologFlag(f);
Sdprintf("OOPS; failed to set Prolog flag!?\n");
}
succeed; succeed;
} else } else
@ -516,9 +573,9 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
#ifndef __YAP_PROLOG__ #ifndef __YAP_PROLOG__
if ( k == ATOM_character_escapes ) if ( k == ATOM_character_escapes )
{ if ( val ) { if ( val )
set(m, CHARESCAPE); set(m, M_CHARESCAPE);
else else
clear(m, CHARESCAPE); clear(m, M_CHARESCAPE);
} else if ( k == ATOM_debug ) } else if ( k == ATOM_debug )
{ if ( val ) { if ( val )
{ debugmode(DBG_ALL, NULL); { debugmode(DBG_ALL, NULL);
@ -551,15 +608,19 @@ set_prolog_flag_unlocked(term_t key, term_t value, int flags)
if ( k == ATOM_double_quotes ) if ( k == ATOM_double_quotes )
{ rval = setDoubleQuotes(a, &m->flags); { rval = setDoubleQuotes(a, &m->flags);
} else if ( k == ATOM_unknown ) } else if ( k == ATOM_unknown )
{ rval = setUnknown(a, &m->flags); { rval = setUnknown(value, a, m);
} else if ( k == ATOM_write_attributes ) } else if ( k == ATOM_write_attributes )
{ rval = setWriteAttributes(a); { rval = setWriteAttributes(a);
} else if ( k == ATOM_occurs_check ) } else if ( k == ATOM_occurs_check )
{ rval = setOccursCheck(a); { rval = setOccursCheck(a);
} else if ( k == ATOM_access_level )
{ rval = setAccessLevelFromAtom(a);
} else } else
#endif #endif
if ( k == ATOM_encoding ) if ( k == ATOM_encoding )
{ rval = setEncoding(a); { rval = setEncoding(a);
} else if ( k == ATOM_stream_type_check )
{ rval = setStreamTypeCheck(a);
} }
if ( !rval ) if ( !rval )
fail; fail;
@ -705,7 +766,7 @@ unify_prolog_flag_value(Module m, atom_t key, prolog_flag *f, term_t val)
#ifndef __YAP_PROLOG__ #ifndef __YAP_PROLOG__
if ( key == ATOM_character_escapes ) if ( key == ATOM_character_escapes )
{ atom_t v = (true(m, CHARESCAPE) ? ATOM_true : ATOM_false); { atom_t v = (true(m, M_CHARESCAPE) ? ATOM_true : ATOM_false);
return PL_unify_atom(val, v); return PL_unify_atom(val, v);
} else if ( key == ATOM_double_quotes ) } else if ( key == ATOM_double_quotes )
@ -736,6 +797,7 @@ unify_prolog_flag_value(Module m, atom_t key, prolog_flag *f, term_t val)
break; break;
default: default:
assert(0); assert(0);
return FALSE;
} }
return PL_unify_atom(val, v); return PL_unify_atom(val, v);
@ -747,6 +809,14 @@ unify_prolog_flag_value(Module m, atom_t key, prolog_flag *f, term_t val)
{ return PL_unify_bool_ex(val, debugstatus.debugging); { return PL_unify_bool_ex(val, debugstatus.debugging);
} else if ( key == ATOM_debugger_show_context ) } else if ( key == ATOM_debugger_show_context )
{ return PL_unify_bool_ex(val, debugstatus.showContext); { return PL_unify_bool_ex(val, debugstatus.showContext);
} else if ( key == ATOM_break_level )
{ int bl = currentBreakLevel();
if ( bl >= 0 )
return PL_unify_integer(val, bl);
return FALSE;
} else if ( key == ATOM_access_level )
{ return PL_unify_atom(val, accessLevel());
} }
#endif /* YAP_PROLOG */ #endif /* YAP_PROLOG */
@ -861,7 +931,7 @@ pl_prolog_flag5(term_t key, term_t value,
fail; fail;
} else if ( PL_is_variable(key) ) } else if ( PL_is_variable(key) )
{ e = allocHeap(sizeof(*e)); { e = allocHeapOrHalt(sizeof(*e));
e->module = module; e->module = module;
@ -965,7 +1035,7 @@ pl_prolog_flag(term_t name, term_t value, control_t h)
#define SO_PATH "LD_LIBRARY_PATH" #define SO_PATH "LD_LIBRARY_PATH"
#endif #endif
void static void
initPrologFlagTable(void) initPrologFlagTable(void)
{ if ( !GD->prolog_flag.table ) { if ( !GD->prolog_flag.table )
{ {
@ -973,7 +1043,7 @@ initPrologFlagTable(void)
initPrologThreads(); /* may be called before PL_initialise() */ initPrologThreads(); /* may be called before PL_initialise() */
#endif #endif
GD->prolog_flag.table = newHTable(32); GD->prolog_flag.table = newHTable(64);
} }
} }
@ -983,7 +1053,7 @@ initPrologFlags(void)
{ GET_LD { GET_LD
#ifndef __YAP_PROLOG__ #ifndef __YAP_PROLOG__
setPrologFlag("iso", FT_BOOL, FALSE, PLFLAG_ISO); setPrologFlag("iso", FT_BOOL, FALSE, PLFLAG_ISO);
setPrologFlag("arch", FT_ATOM|FF_READONLY, ARCH); setPrologFlag("arch", FT_ATOM|FF_READONLY, PLARCH);
#if __WINDOWS__ #if __WINDOWS__
setPrologFlag("windows", FT_BOOL|FF_READONLY, TRUE, 0); setPrologFlag("windows", FT_BOOL|FF_READONLY, TRUE, 0);
#endif #endif
@ -996,12 +1066,17 @@ initPrologFlags(void)
#if defined(HAVE_GETPID) || defined(EMULATE_GETPID) #if defined(HAVE_GETPID) || defined(EMULATE_GETPID)
setPrologFlag("pid", FT_INTEGER|FF_READONLY, getpid()); setPrologFlag("pid", FT_INTEGER|FF_READONLY, getpid());
#endif #endif
setPrologFlag("optimise", FT_BOOL, GD->cmdline.optimise, PLFLAG_OPTIMISE);
setPrologFlag("generate_debug_info", FT_BOOL, setPrologFlag("generate_debug_info", FT_BOOL,
truePrologFlag(PLFLAG_DEBUGINFO), PLFLAG_DEBUGINFO); truePrologFlag(PLFLAG_DEBUGINFO), PLFLAG_DEBUGINFO);
setPrologFlag("last_call_optimisation", FT_BOOL, TRUE, PLFLAG_LASTCALL); setPrologFlag("last_call_optimisation", FT_BOOL, TRUE, PLFLAG_LASTCALL);
setPrologFlag("c_libs", FT_ATOM|FF_READONLY, C_LIBS); setPrologFlag("warn_override_implicit_import", FT_BOOL, TRUE,
setPrologFlag("c_cc", FT_ATOM|FF_READONLY, C_CC); PLFLAG_WARN_OVERRIDE_IMPLICIT_IMPORT);
setPrologFlag("c_ldflags", FT_ATOM|FF_READONLY, C_LDFLAGS); setPrologFlag("c_cc", FT_ATOM, C_CC);
setPrologFlag("c_libs", FT_ATOM, C_LIBS);
setPrologFlag("c_libplso", FT_ATOM, C_LIBPLSO);
setPrologFlag("c_ldflags", FT_ATOM, C_LDFLAGS);
setPrologFlag("c_cflags", FT_ATOM, C_CFLAGS);
#if defined(O_LARGEFILES) || SIZEOF_LONG == 8 #if defined(O_LARGEFILES) || SIZEOF_LONG == 8
setPrologFlag("large_files", FT_BOOL|FF_READONLY, TRUE, 0); setPrologFlag("large_files", FT_BOOL|FF_READONLY, TRUE, 0);
#endif #endif
@ -1041,6 +1116,7 @@ initPrologFlags(void)
setPrologFlag("debug_on_error", FT_BOOL, TRUE, PLFLAG_DEBUG_ON_ERROR); setPrologFlag("debug_on_error", FT_BOOL, TRUE, PLFLAG_DEBUG_ON_ERROR);
setPrologFlag("report_error", FT_BOOL, TRUE, PLFLAG_REPORT_ERROR); setPrologFlag("report_error", FT_BOOL, TRUE, PLFLAG_REPORT_ERROR);
#endif #endif
setPrologFlag("break_level", FT_INTEGER|FF_READONLY, 0, 0);
setPrologFlag("user_flags", FT_ATOM, "silent"); setPrologFlag("user_flags", FT_ATOM, "silent");
setPrologFlag("editor", FT_ATOM, "default"); setPrologFlag("editor", FT_ATOM, "default");
setPrologFlag("debugger_show_context", FT_BOOL, FALSE, 0); setPrologFlag("debugger_show_context", FT_BOOL, FALSE, 0);
@ -1065,28 +1141,39 @@ initPrologFlags(void)
setPrologFlag("integer_rounding_function", FT_ATOM|FF_READONLY, "toward_zero"); setPrologFlag("integer_rounding_function", FT_ATOM|FF_READONLY, "toward_zero");
setPrologFlag("max_arity", FT_ATOM|FF_READONLY, "unbounded"); setPrologFlag("max_arity", FT_ATOM|FF_READONLY, "unbounded");
setPrologFlag("answer_format", FT_ATOM, "~p"); setPrologFlag("answer_format", FT_ATOM, "~p");
setPrologFlag("colon_sets_calling_context", FT_BOOL, TRUE, 0);
setPrologFlag("character_escapes", FT_BOOL, TRUE, PLFLAG_CHARESCAPE); setPrologFlag("character_escapes", FT_BOOL, TRUE, PLFLAG_CHARESCAPE);
setPrologFlag("char_conversion", FT_BOOL, FALSE, PLFLAG_CHARCONVERSION); setPrologFlag("char_conversion", FT_BOOL, FALSE, PLFLAG_CHARCONVERSION);
setPrologFlag("backquoted_string", FT_BOOL, FALSE, PLFLAG_BACKQUOTED_STRING); setPrologFlag("backquoted_string", FT_BOOL, FALSE, PLFLAG_BACKQUOTED_STRING);
setPrologFlag("write_attributes", FT_ATOM, "ignore"); setPrologFlag("write_attributes", FT_ATOM, "ignore");
setPrologFlag("stream_type_check", FT_ATOM, "loose");
setPrologFlag("occurs_check", FT_ATOM, "false"); setPrologFlag("occurs_check", FT_ATOM, "false");
setPrologFlag("access_level", FT_ATOM, "user");
setPrologFlag("double_quotes", FT_ATOM, "codes"); setPrologFlag("double_quotes", FT_ATOM, "codes");
setPrologFlag("unknown", FT_ATOM, "error"); setPrologFlag("unknown", FT_ATOM, "error");
setPrologFlag("debug", FT_BOOL, FALSE, 0); setPrologFlag("debug", FT_BOOL, FALSE, 0);
setPrologFlag("verbose", FT_ATOM|FF_KEEP, GD->options.silent ? "silent" : "normal"); setPrologFlag("verbose", FT_ATOM|FF_KEEP, GD->options.silent ? "silent" : "normal");
setPrologFlag("verbose_load", FT_BOOL, TRUE, 0); setPrologFlag("verbose_load", FT_ATOM, "normal");
setPrologFlag("verbose_autoload", FT_BOOL, FALSE, 0); setPrologFlag("verbose_autoload", FT_BOOL, FALSE, 0);
setPrologFlag("verbose_file_search", FT_BOOL, FALSE, 0); setPrologFlag("verbose_file_search", FT_BOOL, FALSE, 0);
setPrologFlag("allow_variable_name_as_functor", FT_BOOL, FALSE, setPrologFlag("allow_variable_name_as_functor", FT_BOOL, FALSE,
ALLOW_VARNAME_FUNCTOR); ALLOW_VARNAME_FUNCTOR);
setPrologFlag("toplevel_var_size", FT_INTEGER, 1000); setPrologFlag("toplevel_var_size", FT_INTEGER, 1000);
setPrologFlag("toplevel_print_anon", FT_BOOL, TRUE, 0); setPrologFlag("toplevel_print_anon", FT_BOOL, TRUE, 0);
setPrologFlag("toplevel_prompt", FT_ATOM, "~m~d~l~! ?- ");
setPrologFlag("file_name_variables", FT_BOOL, FALSE, PLFLAG_FILEVARS);
setPrologFlag("fileerrors", FT_BOOL, TRUE, PLFLAG_FILEERRORS);
#ifdef __unix__ #ifdef __unix__
setPrologFlag("unix", FT_BOOL|FF_READONLY, TRUE, 0); setPrologFlag("unix", FT_BOOL|FF_READONLY, TRUE, 0);
#endif #endif
setPrologFlag("encoding", FT_ATOM, stringAtom(encoding_to_atom(LD->encoding)));
setPrologFlag("tty_control", FT_BOOL,
truePrologFlag(PLFLAG_TTY_CONTROL), PLFLAG_TTY_CONTROL);
setPrologFlag("signals", FT_BOOL|FF_READONLY, setPrologFlag("signals", FT_BOOL|FF_READONLY,
truePrologFlag(PLFLAG_SIGNALS), PLFLAG_SIGNALS); truePrologFlag(PLFLAG_SIGNALS), PLFLAG_SIGNALS);
setPrologFlag("readline", FT_BOOL/*|FF_READONLY*/, FALSE, 0);
#if defined(__WINDOWS__) && defined(_DEBUG) #if defined(__WINDOWS__) && defined(_DEBUG)
setPrologFlag("kernel_compile_mode", FT_ATOM|FF_READONLY, "debug"); setPrologFlag("kernel_compile_mode", FT_ATOM|FF_READONLY, "debug");
@ -1124,7 +1211,7 @@ initPrologFlags(void)
#ifndef __YAP_PROLOG__ #ifndef __YAP_PROLOG__
static void static void
setArgvPrologFlag() setArgvPrologFlag(void)
{ GET_LD { GET_LD
fid_t fid = PL_open_foreign_frame(); fid_t fid = PL_open_foreign_frame();
term_t e = PL_new_term_ref(); term_t e = PL_new_term_ref();
@ -1148,7 +1235,7 @@ setArgvPrologFlag()
#endif #endif
static void static void
setTZPrologFlag() setTZPrologFlag(void)
{ tzset(); { tzset();
setPrologFlag("timezone", FT_INTEGER|FF_READONLY, timezone); setPrologFlag("timezone", FT_INTEGER|FF_READONLY, timezone);
@ -1166,7 +1253,7 @@ setVersionPrologFlag(void)
int patch = (PLVERSION%100); int patch = (PLVERSION%100);
if ( !PL_unify_term(t, if ( !PL_unify_term(t,
PL_FUNCTOR_CHARS, "swi", 4, PL_FUNCTOR_CHARS, PLNAME, 4,
PL_INT, major, PL_INT, major,
PL_INT, minor, PL_INT, minor,
PL_INT, patch, PL_INT, patch,
@ -1179,6 +1266,19 @@ setVersionPrologFlag(void)
setGITVersion(); setGITVersion();
} }
#endif /* YAP_PROLOG */ #endif /* YAP_PROLOG */
void
cleanupPrologFlags(void)
{ if ( GD->prolog_flag.table )
{ Table t = GD->prolog_flag.table;
GD->prolog_flag.table = NULL;
t->free_symbol = freeSymbolPrologFlagTable;
destroyHTable(t);
}
}
/******************************* /*******************************
* PUBLISH PREDICATES * * PUBLISH PREDICATES *
*******************************/ *******************************/

View File

@ -1,11 +1,10 @@
/* $Id$ /* Part of SWI-Prolog
Part of SWI-Prolog
Author: Jan Wielemaker Author: Jan Wielemaker
E-mail: J.Wielemaker@uva.nl E-mail: J.Wielemaker@vu.nl
WWW: http://www.swi-prolog.org WWW: http://www.swi-prolog.org
Copyright (C): 1985-2009, University of Amsterdam Copyright (C): 1985-2012, University of Amsterdam
VU University Amsterdam
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -19,21 +18,21 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#if defined(__WINDOWS__)||defined(__WIN32) #ifdef __WINDOWS__
#include <windows/uxnt.h> #include "windows/uxnt.h"
#ifndef _YAP_NOT_INSTALLED_
#ifdef WIN64 #ifdef WIN64
#define MD "config/win64.h" #include "config/win64.h"
#else #else
#define MD "config/win32.h" #include "config/win32.h"
#endif
#endif #endif
#include <winsock2.h> #include <winsock2.h>
#include "windows/mswchar.h" #include "windows/mswchar.h"
#define CRLF_MAPPING 1 #define CRLF_MAPPING 1
#else
#include <config.h>
#endif #endif
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -48,12 +47,6 @@ recursive locks. If a stream handle might be known to another thread
locking is required. locking is required.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifdef MD
#include MD
#else
#include <config.h>
#endif
#if _FILE_OFFSET_BITS == 64 || defined(_LARGE_FILES) #if _FILE_OFFSET_BITS == 64 || defined(_LARGE_FILES)
#define O_LARGEFILES 1 /* use for conditional code in Prolog */ #define O_LARGEFILES 1 /* use for conditional code in Prolog */
#else #else
@ -62,8 +55,9 @@ locking is required.
#define PL_KERNEL 1 #define PL_KERNEL 1
#include <wchar.h> #include <wchar.h>
typedef wchar_t pl_wchar_t; #define NEEDS_SWINSOCK
#include "SWI-Stream.h" #include "SWI-Stream.h"
#include "SWI-Prolog.h"
#include "pl-utf8.h" #include "pl-utf8.h"
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
@ -104,7 +98,7 @@ typedef wchar_t pl_wchar_t;
#endif #endif
#define ROUND(p, n) ((((p) + (n) - 1) & ~((n) - 1))) #define ROUND(p, n) ((((p) + (n) - 1) & ~((n) - 1)))
#define UNDO_SIZE ROUND(MB_LEN_MAX, sizeof(wchar_t)) #define UNDO_SIZE ROUND(PL_MB_LEN_MAX, sizeof(wchar_t))
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
@ -127,7 +121,7 @@ static int S__seterror(IOSTREAM *s);
#ifdef O_PLMT #ifdef O_PLMT
#define SLOCK(s) if ( s->mutex ) recursiveMutexLock(s->mutex) #define SLOCK(s) if ( s->mutex ) recursiveMutexLock(s->mutex)
#define SUNLOCK(s) if ( s->mutex ) recursiveMutexUnlock(s->mutex) #define SUNLOCK(s) if ( s->mutex ) recursiveMutexUnlock(s->mutex)
static inline int inline int
STRYLOCK(IOSTREAM *s) STRYLOCK(IOSTREAM *s)
{ if ( s->mutex && { if ( s->mutex &&
recursiveMutexTryLock(s->mutex) == EBUSY ) recursiveMutexTryLock(s->mutex) == EBUSY )
@ -141,10 +135,6 @@ STRYLOCK(IOSTREAM *s)
#define STRYLOCK(s) (TRUE) #define STRYLOCK(s) (TRUE)
#endif #endif
typedef void *record_t;
typedef void *Module;
typedef intptr_t term_t;
typedef intptr_t atom_t;
#include "pl-error.h" #include "pl-error.h"
extern int fatalError(const char *fm, ...); extern int fatalError(const char *fm, ...);
@ -368,6 +358,69 @@ Sunlock(IOSTREAM *s)
} }
/*******************************
* TIMEOUT *
*******************************/
#ifdef HAVE_SELECT
#ifndef __WINDOWS__
typedef int SOCKET;
#define INVALID_SOCKET -1
#define Swinsock(s) Sfileno(s)
#define NFDS(n) (n+1)
#else
#define NFDS(n) (0) /* 1st arg of select is ignored */
#endif
static int
S__wait(IOSTREAM *s)
{ SOCKET fd = Swinsock(s);
fd_set wait;
struct timeval time;
int rc;
if ( fd == INVALID_SOCKET )
{ errno = EPERM; /* no permission to select */
s->flags |= SIO_FERR;
return -1;
}
time.tv_sec = s->timeout / 1000;
time.tv_usec = (s->timeout % 1000) * 1000;
FD_ZERO(&wait);
FD_SET(fd, &wait);
for(;;)
{ if ( (s->flags & SIO_INPUT) )
rc = select(NFDS(fd), &wait, NULL, NULL, &time);
else
rc = select(NFDS(fd), NULL, &wait, NULL, &time);
if ( rc < 0 && errno == EINTR )
{ if ( PL_handle_signals() < 0 )
{ errno = EPLEXCEPTION;
return -1;
}
continue;
}
break;
}
if ( rc == 0 )
{ s->flags |= (SIO_TIMEOUT|SIO_FERR);
return -1;
}
return 0; /* ok, data available */
}
#endif /*HAVE_SELECT*/
/******************************* /*******************************
* FLUSH/FILL * * FLUSH/FILL *
*******************************/ *******************************/
@ -385,7 +438,18 @@ S__flushbuf(IOSTREAM *s)
while ( from < to ) while ( from < to )
{ size_t size = (size_t)(to - from); { size_t size = (size_t)(to - from);
ssize_t n = (*s->functions->write)(s->handle, from, size); ssize_t n;
#ifdef HAVE_SELECT
s->flags &= ~SIO_TIMEOUT;
if ( s->timeout >= 0 )
{ if ( (rc=S__wait(s)) < 0 )
goto partial;
}
#endif
n = (*s->functions->write)(s->handle, from, size);
if ( n > 0 ) /* wrote some */ if ( n > 0 ) /* wrote some */
{ from += n; { from += n;
@ -398,6 +462,9 @@ S__flushbuf(IOSTREAM *s)
} }
} }
#ifdef HAVE_SELECT
partial:
#endif
if ( to == from ) /* full flush */ if ( to == from ) /* full flush */
{ rc = s->bufp - s->buffer; { rc = s->bufp - s->buffer;
s->bufp = s->buffer; s->bufp = s->buffer;
@ -442,52 +509,6 @@ S__flushbufc(int c, IOSTREAM *s)
} }
static int
Swait_for_data(IOSTREAM *s)
{ int fd = Sfileno(s);
fd_set wait;
struct timeval time;
int rc;
if ( fd < 0 )
{ errno = EPERM; /* no permission to select */
s->flags |= SIO_FERR;
return -1;
}
time.tv_sec = s->timeout / 1000;
time.tv_usec = (s->timeout % 1000) * 1000;
FD_ZERO(&wait);
#ifdef __WINDOWS__
FD_SET((SOCKET)fd, &wait);
#else
FD_SET(fd, &wait);
#endif
for(;;)
{ rc = select(fd+1, &wait, NULL, NULL, &time);
if ( rc < 0 && errno == EINTR )
{ if ( PL_handle_signals() < 0 )
{ errno = EPLEXCEPTION;
return -1;
}
continue;
}
break;
}
if ( rc == 0 )
{ s->flags |= (SIO_TIMEOUT|SIO_FERR);
return -1;
}
return 0; /* ok, data available */
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
S__fillbuf() fills the read-buffer, returning the first character of it. S__fillbuf() fills the read-buffer, returning the first character of it.
It also realises the SWI-Prolog timeout facility. It also realises the SWI-Prolog timeout facility.
@ -497,8 +518,11 @@ int
S__fillbuf(IOSTREAM *s) S__fillbuf(IOSTREAM *s)
{ int c; { int c;
if ( s->flags & (SIO_FEOF|SIO_FERR) ) if ( s->flags & (SIO_FEOF|SIO_FERR) ) /* reading past eof */
{ s->flags |= SIO_FEOF2; /* reading past eof */ { if ( s->flags & SIO_FEOF2ERR )
s->flags |= (SIO_FEOF2|SIO_FERR);
else
s->flags |= SIO_FEOF2;
return -1; return -1;
} }
@ -508,7 +532,7 @@ S__fillbuf(IOSTREAM *s)
if ( s->timeout >= 0 && !s->downstream ) if ( s->timeout >= 0 && !s->downstream )
{ int rc; { int rc;
if ( (rc=Swait_for_data(s)) < 0 ) if ( (rc=S__wait(s)) < 0 )
return rc; return rc;
} }
#endif #endif
@ -517,7 +541,8 @@ S__fillbuf(IOSTREAM *s)
{ char chr; { char chr;
ssize_t n; ssize_t n;
if ( (n=(*s->functions->read)(s->handle, &chr, 1)) == 1 ) n = (*s->functions->read)(s->handle, &chr, 1);
if ( n == 1 )
{ c = char_to_int(chr); { c = char_to_int(chr);
return c; return c;
} else if ( n == 0 ) } else if ( n == 0 )
@ -548,7 +573,8 @@ S__fillbuf(IOSTREAM *s)
len = s->bufsize; len = s->bufsize;
} }
if ( (n=(*s->functions->read)(s->handle, s->limitp, len)) > 0 ) n = (*s->functions->read)(s->handle, s->limitp, len);
if ( n > 0 )
{ s->limitp += n; { s->limitp += n;
c = char_to_int(*s->bufp++); c = char_to_int(*s->bufp++);
return c; return c;
@ -777,7 +803,7 @@ put_code(int c, IOSTREAM *s)
} }
goto simple; goto simple;
case ENC_ANSI: case ENC_ANSI:
{ char b[MB_LEN_MAX]; { char b[PL_MB_LEN_MAX];
size_t n; size_t n;
if ( !s->mbstate ) if ( !s->mbstate )
@ -863,7 +889,10 @@ Sputcode(int c, IOSTREAM *s)
if ( s->tee && s->tee->magic == SIO_MAGIC ) if ( s->tee && s->tee->magic == SIO_MAGIC )
Sputcode(c, s->tee); Sputcode(c, s->tee);
if ( c == '\n' && (s->flags&SIO_TEXT) && s->newline == SIO_NL_DOS ) if ( c == '\n' &&
(s->flags&SIO_TEXT) &&
s->newline == SIO_NL_DOS &&
s->lastc != '\r' )
{ if ( put_code('\r', s) < 0 ) { if ( put_code('\r', s) < 0 )
return -1; return -1;
} }
@ -886,7 +915,7 @@ Scanrepresent(int c, IOSTREAM *s)
return -1; return -1;
case ENC_ANSI: case ENC_ANSI:
{ mbstate_t state; { mbstate_t state;
char b[MB_LEN_MAX]; char b[PL_MB_LEN_MAX];
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
if ( wcrtomb(b, (wchar_t)c, &state) != (size_t)-1 ) if ( wcrtomb(b, (wchar_t)c, &state) != (size_t)-1 )
@ -1072,14 +1101,15 @@ returns \n, but it returns the same for a single \n.
Often, we could keep track of bufp and reset this, but we must deal with Often, we could keep track of bufp and reset this, but we must deal with
the case where we fetch a new buffer. In this case, we must copy the few the case where we fetch a new buffer. In this case, we must copy the few
remaining bytes to the `unbuffer' area. remaining bytes to the `unbuffer' area. If SIO_USERBUF is set, we do not
have this spare buffer space. This is used for reading from strings,
which cannot fetch a new buffer anyway.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int int
Speekcode(IOSTREAM *s) Speekcode(IOSTREAM *s)
{ int c; { int c;
char *start; char *start;
IOPOS *psave = s->position;
size_t safe = (size_t)-1; size_t safe = (size_t)-1;
if ( !s->buffer ) if ( !s->buffer )
@ -1094,15 +1124,19 @@ Speekcode(IOSTREAM *s)
if ( (s->flags & SIO_FEOF) ) if ( (s->flags & SIO_FEOF) )
return -1; return -1;
if ( s->bufp + UNDO_SIZE > s->limitp ) if ( s->bufp + UNDO_SIZE > s->limitp && !(s->flags&SIO_USERBUF) )
{ safe = s->limitp - s->bufp; { safe = s->limitp - s->bufp;
memcpy(s->buffer-safe, s->bufp, safe); memcpy(s->buffer-safe, s->bufp, safe);
} }
start = s->bufp; start = s->bufp;
s->position = NULL; if ( s->position )
{ IOPOS psave = *s->position;
c = Sgetcode(s); c = Sgetcode(s);
s->position = psave; *s->position = psave;
} else
{ c = Sgetcode(s);
}
if ( Sferror(s) ) if ( Sferror(s) )
return -1; return -1;
@ -1110,7 +1144,7 @@ Speekcode(IOSTREAM *s)
if ( s->bufp > start ) if ( s->bufp > start )
{ s->bufp = start; { s->bufp = start;
} else } else if ( c != -1 )
{ assert(safe != (size_t)-1); { assert(safe != (size_t)-1);
s->bufp = s->buffer-safe; s->bufp = s->buffer-safe;
} }
@ -1341,10 +1375,6 @@ Sfeof(IOSTREAM *s)
return -1; return -1;
} }
if ( s->downstream != NULL &&
Sfeof(s->downstream))
return TRUE;
if ( S__fillbuf(s) == -1 ) if ( S__fillbuf(s) == -1 )
return TRUE; return TRUE;
@ -1440,6 +1470,11 @@ Ssetenc(IOSTREAM *s, IOENC enc, IOENC *old)
} }
s->encoding = enc; s->encoding = enc;
if ( enc == ENC_OCTET )
s->flags &= ~SIO_TEXT;
else
s->flags |= SIO_TEXT;
return 0; return 0;
} }
@ -1490,23 +1525,23 @@ Sunit_size(IOSTREAM *s)
Return the size of the underlying data object. Should be optimized; Return the size of the underlying data object. Should be optimized;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
long int64_t
Ssize(IOSTREAM *s) Ssize(IOSTREAM *s)
{ if ( s->functions->control ) { if ( s->functions->control )
{ long size; { int64_t size;
if ( (*s->functions->control)(s->handle, SIO_GETSIZE, (void *)&size) == 0 ) if ( (*s->functions->control)(s->handle, SIO_GETSIZE, (void *)&size) == 0 )
return size; return size;
} }
if ( s->functions->seek ) if ( s->functions->seek )
{ long here = Stell(s); { int64_t here = Stell64(s);
long end; int64_t end;
if ( Sseek(s, 0, SIO_SEEK_END) == 0 ) if ( Sseek64(s, 0, SIO_SEEK_END) == 0 )
end = Stell(s); end = Stell64(s);
else else
end = -1; end = -1;
Sseek(s, here, SIO_SEEK_SET); Sseek64(s, here, SIO_SEEK_SET);
return end; return end;
} }
@ -1667,13 +1702,13 @@ unallocStream(IOSTREAM *s)
#ifdef O_PLMT #ifdef O_PLMT
if ( s->mutex ) if ( s->mutex )
{ recursiveMutexDelete(s->mutex); { recursiveMutexDelete(s->mutex);
free(s->mutex); PL_free(s->mutex);
s->mutex = NULL; s->mutex = NULL;
} }
#endif #endif
if ( !(s->flags & SIO_STATIC) ) if ( !(s->flags & SIO_STATIC) )
free(s); PL_free(s);
} }
@ -1711,7 +1746,7 @@ Sclose(IOSTREAM *s)
#ifdef __WINDOWS__ #ifdef __WINDOWS__
if ( (s->flags & SIO_ADVLOCK) ) if ( (s->flags & SIO_ADVLOCK) )
{ OVERLAPPED ov; { OVERLAPPED ov;
HANDLE h = (HANDLE)_get_osfhandle((int)s->handle); HANDLE h = (HANDLE)_get_osfhandle((int)((uintptr_t)s->handle));
memset(&ov, 0, sizeof(ov)); memset(&ov, 0, sizeof(ov));
UnlockFileEx(h, 0, 0, 0xffffffff, &ov); UnlockFileEx(h, 0, 0, 0xffffffff, &ov);
@ -1732,9 +1767,9 @@ Sclose(IOSTREAM *s)
if ( rval < 0 ) if ( rval < 0 )
reportStreamError(s); reportStreamError(s);
run_close_hooks(s); /* deletes Prolog registration */ run_close_hooks(s); /* deletes Prolog registration */
s->magic = SIO_CMAGIC;
SUNLOCK(s); SUNLOCK(s);
s->magic = SIO_CMAGIC;
if ( s->message ) if ( s->message )
free(s->message); free(s->message);
if ( s->references == 0 ) if ( s->references == 0 )
@ -1845,10 +1880,22 @@ Svprintf(const char *fm, va_list args)
} }
#define NEXTCHR(s, c) if ( utf8 ) \ #define NEXTCHR(s, c) \
{ (s) = utf8_get_char((s), &(c)); \ switch (enc) \
} else \ { case ENC_ANSI: \
{ c = *(s)++; c &= 0xff; \ c = *(s)++; c &= 0xff; \
break; \
case ENC_UTF8: \
(s) = utf8_get_char((s), &(c)); \
break; \
case ENC_WCHAR: \
{ wchar_t *_w = (wchar_t*)(s); \
c = *_w++; \
(s) = (char*)_w; \
break; \
} \
default: \
break; \
} }
#define OUTCHR(s, c) do { printed++; \ #define OUTCHR(s, c) do { printed++; \
@ -1911,7 +1958,7 @@ Svfprintf(IOSTREAM *s, const char *fm, va_list args)
char fbuf[100], *fs = fbuf, *fe = fbuf; char fbuf[100], *fs = fbuf, *fe = fbuf;
int islong = 0; int islong = 0;
int pad = ' '; int pad = ' ';
int utf8 = FALSE; IOENC enc = ENC_ANSI;
for(;;) for(;;)
{ switch(*fm) { switch(*fm)
@ -1952,13 +1999,19 @@ Svfprintf(IOSTREAM *s, const char *fm, va_list args)
{ islong++; /* 1: %ld */ { islong++; /* 1: %ld */
fm++; fm++;
} }
if ( *fm == 'l' ) switch ( *fm )
{ islong++; /* 2: %lld */ { case 'l':
islong++; /* 2: %lld */
fm++; fm++;
} break;
if ( *fm == 'U' ) /* %Us: UTF-8 string */ case 'U': /* %Us: UTF-8 string */
{ utf8 = TRUE; enc = ENC_UTF8;
fm++; fm++;
break;
case 'W': /* %Ws: wide string */
enc = ENC_WCHAR;
fm++;
break;
} }
switch(*fm) switch(*fm)
@ -1983,41 +2036,53 @@ Svfprintf(IOSTREAM *s, const char *fm, va_list args)
case 'u': case 'u':
case 'x': case 'x':
case 'X': case 'X':
{ intptr_t v = 0; /* make compiler silent */ { int vi = 0;
int64_t vl = 0; long vl = 0; /* make compiler silent */
int64_t vll = 0;
char fmbuf[8], *fp=fmbuf; char fmbuf[8], *fp=fmbuf;
switch( islong ) switch( islong )
{ case 0: { case 0:
v = va_arg(args, int); vi = va_arg(args, int);
break; break;
case 1: case 1:
v = va_arg(args, long); vl = va_arg(args, long);
break; break;
case 2: case 2:
vl = va_arg(args, int64_t); vll = va_arg(args, int64_t);
break; break;
default:
assert(0);
} }
*fp++ = '%'; *fp++ = '%';
if ( modified ) if ( modified )
*fp++ = '#'; *fp++ = '#';
*fp++ = 'l'; switch( islong )
if ( islong < 2 ) { case 0:
{ *fp++ = *fm; *fp++ = *fm;
*fp = '\0'; *fp = '\0';
SNPRINTF3(fmbuf, v); SNPRINTF3(fmbuf, vi);
} else break;
{ case 1:
*fp++ = 'l';
*fp++ = *fm;
*fp = '\0';
SNPRINTF3(fmbuf, vl);
break;
case 2:
#ifdef __WINDOWS__ #ifdef __WINDOWS__
strcat(fp-1, "I64"); /* Synchronise with INT64_FORMAT! */ *fp++ = 'I'; /* Synchronise with INT64_FORMAT! */
fp += strlen(fp); *fp++ = '6';
*fp++ = '4';
#else #else
*fp++ = 'l'; *fp++ = 'l';
*fp++ = 'l';
#endif #endif
*fp++ = *fm; *fp++ = *fm;
*fp = '\0'; *fp = '\0';
SNPRINTF3(fmbuf, vl); SNPRINTF3(fmbuf, vll);
break;
} }
break; break;
@ -2075,12 +2140,25 @@ Svfprintf(IOSTREAM *s, const char *fm, va_list args)
{ size_t w; { size_t w;
if ( fs == fbuf ) if ( fs == fbuf )
w = fe - fs; { w = fe - fs;
else } else
{ switch(enc)
{ case ENC_ANSI:
w = strlen(fs);
break;
case ENC_UTF8:
w = strlen(fs); w = strlen(fs);
if ( utf8 )
w = utf8_strlen(fs, w); w = utf8_strlen(fs, w);
break;
case ENC_WCHAR:
w = wcslen((wchar_t*)fs);
break;
default:
assert(0);
w = 0; /* make compiler happy */
break;
}
}
if ( (ssize_t)w < arg1 ) if ( (ssize_t)w < arg1 )
{ w = arg1 - w; { w = arg1 - w;
@ -2609,7 +2687,7 @@ Scontrol_file(void *handle, int action, void *arg)
switch(action) switch(action)
{ case SIO_GETSIZE: { case SIO_GETSIZE:
{ intptr_t *rval = arg; { int64_t *rval = arg;
struct stat buf; struct stat buf;
if ( fstat(fd, &buf) == 0 ) if ( fstat(fd, &buf) == 0 )
@ -2621,6 +2699,11 @@ Scontrol_file(void *handle, int action, void *arg)
case SIO_SETENCODING: case SIO_SETENCODING:
case SIO_FLUSHOUTPUT: case SIO_FLUSHOUTPUT:
return 0; return 0;
case SIO_GETFILENO:
{ int *p = arg;
*p = fd;
return 0;
}
default: default:
return -1; return -1;
} }
@ -2662,13 +2745,20 @@ provide the socket-id through Sfileno, this code crashes on
tcp_open_socket(). As ttys and its detection is of no value on Windows tcp_open_socket(). As ttys and its detection is of no value on Windows
anyway, we skip this. Second, Windows doesn't have fork(), so FD_CLOEXEC anyway, we skip this. Second, Windows doesn't have fork(), so FD_CLOEXEC
is of no value. is of no value.
For now, we use PL_malloc_uncollectable(). In the end, this is really
one of the object-types we want to leave to GC.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef FD_CLOEXEC /* This is not defined in MacOS */
#define FD_CLOEXEC 1
#endif
IOSTREAM * IOSTREAM *
Snew(void *handle, int flags, IOFUNCTIONS *functions) Snew(void *handle, int flags, IOFUNCTIONS *functions)
{ IOSTREAM *s; { IOSTREAM *s;
if ( !(s = malloc(sizeof(IOSTREAM))) ) if ( !(s = PL_malloc_uncollectable(sizeof(IOSTREAM))) )
{ errno = ENOMEM; { errno = ENOMEM;
return NULL; return NULL;
} }
@ -2680,7 +2770,11 @@ Snew(void *handle, int flags, IOFUNCTIONS *functions)
s->functions = functions; s->functions = functions;
s->timeout = -1; /* infinite */ s->timeout = -1; /* infinite */
s->posbuf.lineno = 1; s->posbuf.lineno = 1;
s->encoding = ENC_ISO_LATIN_1; if ( (flags&SIO_TEXT) )
{ s->encoding = initEncoding();
} else
{ s->encoding = ENC_OCTET;
}
#if CRLF_MAPPING #if CRLF_MAPPING
s->newline = SIO_NL_DOS; s->newline = SIO_NL_DOS;
#endif #endif
@ -2688,8 +2782,8 @@ Snew(void *handle, int flags, IOFUNCTIONS *functions)
s->position = &s->posbuf; s->position = &s->posbuf;
#ifdef O_PLMT #ifdef O_PLMT
if ( !(flags & SIO_NOMUTEX) ) if ( !(flags & SIO_NOMUTEX) )
{ if ( !(s->mutex = malloc(sizeof(recursiveMutex))) ) { if ( !(s->mutex = PL_malloc(sizeof(recursiveMutex))) )
{ free(s); { PL_free(s);
return NULL; return NULL;
} }
recursiveMutexInit(s->mutex); recursiveMutexInit(s->mutex);
@ -2701,7 +2795,7 @@ Snew(void *handle, int flags, IOFUNCTIONS *functions)
if ( (fd = Sfileno(s)) >= 0 ) if ( (fd = Sfileno(s)) >= 0 )
{ if ( isatty(fd) ) { if ( isatty(fd) )
s->flags |= SIO_ISATTY; s->flags |= SIO_ISATTY;
#if defined(F_SETFD) && defined(FD_CLOEXEC) #ifdef F_SETFD
fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif #endif
} }
@ -2804,14 +2898,24 @@ Sopen_file(const char *path, const char *how)
struct flock buf; struct flock buf;
memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
buf.l_whence = SEEK_SET;
buf.l_type = (lock == lread ? F_RDLCK : F_WRLCK); buf.l_type = (lock == lread ? F_RDLCK : F_WRLCK);
if ( fcntl(fd, wait ? F_SETLKW : F_SETLK, &buf) < 0 ) while( fcntl(fd, wait ? F_SETLKW : F_SETLK, &buf) != 0 )
{ if ( errno == EINTR )
{ if ( PL_handle_signals() < 0 )
{ close(fd);
return NULL;
}
continue;
} else
{ int save = errno; { int save = errno;
close(fd); close(fd);
errno = save; errno = save;
return NULL; return NULL;
} }
}
#else /* we don't have locking */ #else /* we don't have locking */
#if __WINDOWS__ #if __WINDOWS__
HANDLE h = (HANDLE)_get_osfhandle(fd); HANDLE h = (HANDLE)_get_osfhandle(fd);
@ -2891,8 +2995,6 @@ Sfileno(IOSTREAM *s)
if ( s->flags & SIO_FILE ) if ( s->flags & SIO_FILE )
{ intptr_t h = (intptr_t)s->handle; { intptr_t h = (intptr_t)s->handle;
n = (int)h; n = (int)h;
} else if ( s->flags & SIO_PIPE )
{ n = fileno((FILE *)s->handle);
} else if ( s->functions->control && } else if ( s->functions->control &&
(*s->functions->control)(s->handle, (*s->functions->control)(s->handle,
SIO_GETFILENO, SIO_GETFILENO,
@ -2907,6 +3009,30 @@ Sfileno(IOSTREAM *s)
} }
#ifdef __WINDOWS__
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
On Windows, type SOCKET is an unsigned int and all values
[0..INVALID_SOCKET) are valid. It is also not allowed to run normal
file-functions on it or the application will crash. There seems to be no
way out except for introducing an extra function at this level :-(
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
SOCKET
Swinsock(IOSTREAM *s)
{ SOCKET n = INVALID_SOCKET;
if ( s->functions->control &&
(*s->functions->control)(s->handle,
SIO_GETWINSOCK,
(void *)&n) == 0 )
{ return n;
}
errno = EINVAL;
return INVALID_SOCKET;
}
#endif
/******************************* /*******************************
* PIPES * * PIPES *
*******************************/ *******************************/
@ -2915,13 +3041,9 @@ Sfileno(IOSTREAM *s)
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include "windows/popen.c" #include "windows/popen.c"
#ifdef popen
#undef popen #undef popen
#endif
#define popen(cmd, how) pt_popen(cmd, how)
#ifdef pclose
#undef pclose #undef pclose
#endif #define popen(cmd, how) pt_popen(cmd, how)
#define pclose(fd) pt_pclose(fd) #define pclose(fd) pt_pclose(fd)
#endif #endif
@ -2958,11 +3080,31 @@ Sclose_pipe(void *handle)
} }
static int
Scontrol_pipe(void *handle, int action, void *arg)
{ FILE *fp = handle;
switch(action)
{ case SIO_GETFILENO:
{ int *ap = arg;
*ap = fileno(fp);
return 0;
}
case SIO_FLUSHOUTPUT:
case SIO_SETENCODING:
return 0;
default:
return -1;
}
}
IOFUNCTIONS Spipefunctions = IOFUNCTIONS Spipefunctions =
{ Sread_pipe, { Sread_pipe,
Swrite_pipe, Swrite_pipe,
(Sseek_function)0, (Sseek_function)0,
Sclose_pipe Sclose_pipe,
Scontrol_pipe
}; };
@ -2983,9 +3125,9 @@ Sopen_pipe(const char *command, const char *type)
{ int flags; { int flags;
if ( *type == 'r' ) if ( *type == 'r' )
flags = SIO_PIPE|SIO_INPUT|SIO_FBUF; flags = SIO_INPUT|SIO_FBUF;
else else
flags = SIO_PIPE|SIO_OUTPUT|SIO_FBUF; flags = SIO_OUTPUT|SIO_FBUF;
return Snew((void *)fd, flags, &Spipefunctions); return Snew((void *)fd, flags, &Spipefunctions);
} }
@ -3229,12 +3371,20 @@ Sopenmem(char **buffer, size_t *sizep, const char *mode)
static ssize_t static ssize_t
Sread_string(void *handle, char *buf, size_t size) Sread_string(void *handle, char *buf, size_t size)
{ return 0; /* signal EOF */ { (void)handle;
(void)buf;
(void)size;
return 0; /* signal EOF */
} }
static ssize_t static ssize_t
Swrite_string(void *handle, char *buf, size_t size) Swrite_string(void *handle, char *buf, size_t size)
{ errno = ENOSPC; /* signal error */ { (void)handle;
(void)buf;
(void)size;
errno = ENOSPC; /* signal error */
return -1; return -1;
} }
@ -3267,7 +3417,7 @@ Sopen_string(IOSTREAM *s, char *buf, size_t size, const char *mode)
{ int flags = SIO_FBUF|SIO_USERBUF; { int flags = SIO_FBUF|SIO_USERBUF;
if ( !s ) if ( !s )
{ if ( !(s = malloc(sizeof(IOSTREAM))) ) { if ( !(s = PL_malloc_uncollectable(sizeof(IOSTREAM))) ) /* TBD: Use GC */
{ errno = ENOMEM; { errno = ENOMEM;
return NULL; return NULL;
} }
@ -3310,7 +3460,7 @@ Sopen_string(IOSTREAM *s, char *buf, size_t size, const char *mode)
#define STDIO(n, f) { NULL, NULL, NULL, NULL, \ #define STDIO(n, f) { NULL, NULL, NULL, NULL, \
EOF, SIO_MAGIC, 0, f, {0, 0, 0}, NULL, \ EOF, SIO_MAGIC, 0, f, {0, 0, 0}, NULL, \
((void *)(n)), &Sttyfunctions, \ (void *)(n), &Sttyfunctions, \
0, NULL, \ 0, NULL, \
(void (*)(void *))0, NULL, \ (void (*)(void *))0, NULL, \
-1, \ -1, \
@ -3335,31 +3485,33 @@ static const IOSTREAM S__iob0[] =
}; };
/* vsc: Scleanup should reset init done */ static int S__initialised = FALSE;
static int done;
void void
SinitStreams(void) SinitStreams(void)
{ { if ( !S__initialised )
if ( !done++ )
{ int i; { int i;
IOENC enc = initEncoding(); IOENC enc;
S__initialised = TRUE;
enc = initEncoding();
for(i=0; i<=2; i++) for(i=0; i<=2; i++)
{ if ( !isatty(i) ) { IOSTREAM *s = &S__iob[i];
{ S__iob[i].flags &= ~SIO_ISATTY;
S__iob[i].functions = &Sfilefunctions; /* Check for pipe? */ if ( !isatty(i) )
{ s->flags &= ~SIO_ISATTY;
s->functions = &Sfilefunctions; /* Check for pipe? */
} }
if ( S__iob[i].encoding == ENC_ISO_LATIN_1 ) if ( s->encoding == ENC_ISO_LATIN_1 )
S__iob[i].encoding = enc; s->encoding = enc;
#ifdef O_PLMT #ifdef O_PLMT
S__iob[i].mutex = malloc(sizeof(recursiveMutex)); s->mutex = PL_malloc(sizeof(recursiveMutex));
recursiveMutexInit(S__iob[i].mutex); recursiveMutexInit(s->mutex);
#endif #endif
#if CRLF_MAPPING #if CRLF_MAPPING
_setmode(i, O_BINARY); _setmode(i, O_BINARY);
S__iob[i].newline = SIO_NL_DOS; s->newline = SIO_NL_DOS;
#endif #endif
} }
@ -3461,11 +3613,12 @@ Scleanup(void)
S__iob[i].mutex = NULL; S__iob[i].mutex = NULL;
recursiveMutexDelete(m); recursiveMutexDelete(m);
free(m); PL_free(m);
} }
#endif #endif
*s = S__iob0[i]; /* re-initialise */ *s = S__iob0[i]; /* re-initialise */
} }
done = 0;
S__initialised = FALSE;
} }

View File

@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "pl-incl.h" #include "pl-incl.h"
@ -34,45 +34,10 @@ String operations that are needed for the shared IO library.
* ALLOCATION * * ALLOCATION *
*******************************/ *******************************/
#ifdef O_DEBUG
#define CHAR_INUSE 0x42
#define CHAR_FREED 0x41
char * char *
store_string(const char *s) store_string(const char *s)
{ if ( s ) { if ( s )
{ GET_LD { char *copy = (char *)allocHeapOrHalt(strlen(s)+1);
char *copy = (char *)allocHeap(strlen(s)+2);
*copy++ = CHAR_INUSE;
strcpy(copy, s);
return copy;
} else
{ return NULL;
}
}
void
remove_string(char *s)
{ if ( s )
{ GET_LD
assert(s[-1] == CHAR_INUSE);
s[-1] = CHAR_FREED;
freeHeap(s-1, strlen(s)+2);
}
}
#else /*O_DEBUG*/
char *
store_string(const char *s)
{ if ( s )
{ GET_LD
char *copy = (char *)allocHeap(strlen(s)+1);
strcpy(copy, s); strcpy(copy, s);
return copy; return copy;
@ -85,13 +50,8 @@ store_string(const char *s)
void void
remove_string(char *s) remove_string(char *s)
{ if ( s ) { if ( s )
{ GET_LD
freeHeap(s, strlen(s)+1); freeHeap(s, strlen(s)+1);
} }
}
#endif /*O_DEBUG*/
/******************************* /*******************************
* NUMBERS * * NUMBERS *
@ -239,13 +199,13 @@ int_mbscoll(const char *s1, const char *s2, int icase)
if ( l1 < 1024 && (w1 = alloca(sizeof(wchar_t)*(l1+1))) ) if ( l1 < 1024 && (w1 = alloca(sizeof(wchar_t)*(l1+1))) )
{ ml1 = FALSE; { ml1 = FALSE;
} else } else
{ w1 = PL_malloc(sizeof(wchar_t)*(l1+1)); { w1 = PL_malloc_atomic(sizeof(wchar_t)*(l1+1));
ml1 = TRUE; ml1 = TRUE;
} }
if ( l2 < 1024 && (w2 = alloca(sizeof(wchar_t)*(l2+1))) ) if ( l2 < 1024 && (w2 = alloca(sizeof(wchar_t)*(l2+1))) )
{ ml2 = FALSE; { ml2 = FALSE;
} else } else
{ w2 = PL_malloc(sizeof(wchar_t)*(l2+1)); { w2 = PL_malloc_atomic(sizeof(wchar_t)*(l2+1));
ml2 = TRUE; ml2 = TRUE;
} }

View File

@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef PL_STRING_H_INCLUDED #ifndef PL_STRING_H_INCLUDED
@ -27,7 +27,7 @@
COMMON(char *) store_string(const char *s); COMMON(char *) store_string(const char *s);
COMMON(void) remove_string(char *s); COMMON(void) remove_string(char *s);
COMMON(char) digitName(int n, int smll); COMMON(char) digitName(int n, int small);
COMMON(int) digitValue(int b, int c); COMMON(int) digitValue(int b, int c);
COMMON(bool) strprefix(const char *string, const char *prefix); COMMON(bool) strprefix(const char *string, const char *prefix);
COMMON(bool) strpostfix(const char *string, const char *postfix); COMMON(bool) strpostfix(const char *string, const char *postfix);

View File

@ -1,11 +1,10 @@
/* $Id$ /* Part of SWI-Prolog
Part of SWI-Prolog
Author: Jan Wielemaker Author: Jan Wielemaker
E-mail: jan@swi.psy.uva.nl E-mail: J.Wielemaker@vu.nl
WWW: http://www.swi-prolog.org WWW: http://www.swi-prolog.org
Copyright (C): 1985-2002, University of Amsterdam Copyright (C): 1985-2012, University of Amsterdam
VU University Amsterdam
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -19,7 +18,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/*#define O_DEBUG 1*/ /*#define O_DEBUG 1*/
@ -41,35 +40,35 @@ create, advance over and destroy enumerator objects. These objects are
used to enumerate the symbols of these tables, used primarily for the used to enumerate the symbols of these tables, used primarily for the
pl_current_* predicates. pl_current_* predicates.
The enumerators cause two things: (1) as intptr_t enumerators are The enumerators cause two things: (1) as long as enumerators are
associated, the table will not be rehashed and (2) if symbols are associated, the table will not be rehashed and (2) if symbols are
deleted that are referenced by an enumerator, the enumerator is deleted that are referenced by an enumerator, the enumerator is
automatically advanced to the next free symbol. This, in general, makes automatically advanced to the next free symbol. This, in general, makes
the enumeration of hash-tables safe. the enumeration of hash-tables safe.
TODO: abort should delete any pending enumerators. This should be TBD: Resizing hash-tables causes major headaches for concurrent access.
thread-local, as thread_exit/1 should do the same. We can avoid this by using a dynamic array for the list of hash-entries.
Ongoing work in the RDF store shows hash-tables that can handle
concurrent lock-free access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static void static Symbol *
allocHTableEntries(Table ht) allocHTableEntries(int buckets)
{ GET_LD { size_t bytes = buckets * sizeof(Symbol);
int n;
Symbol *p; Symbol *p;
ht->entries = allocHeap(ht->buckets * sizeof(Symbol)); p = allocHeapOrHalt(bytes);
memset(p, 0, bytes);
for(n=0, p = &ht->entries[0]; n < ht->buckets; n++, p++) return p;
*p = NULL;
} }
Table Table
newHTable(int buckets) newHTable(int buckets)
{ GET_LD { Table ht;
Table ht;
ht = allocHeap(sizeof(struct table)); ht = allocHeapOrHalt(sizeof(struct table));
ht->buckets = (buckets & ~TABLE_MASK); ht->buckets = (buckets & ~TABLE_MASK);
ht->size = 0; ht->size = 0;
ht->enumerators = NULL; ht->enumerators = NULL;
@ -79,20 +78,19 @@ newHTable(int buckets)
if ( (buckets & TABLE_UNLOCKED) ) if ( (buckets & TABLE_UNLOCKED) )
ht->mutex = NULL; ht->mutex = NULL;
else else
{ ht->mutex = allocHeap(sizeof(simpleMutex)); { ht->mutex = allocHeapOrHalt(sizeof(simpleMutex));
simpleMutexInit(ht->mutex); simpleMutexInit(ht->mutex);
} }
#endif #endif
allocHTableEntries(ht); ht->entries = allocHTableEntries(ht->buckets);
return ht; return ht;
} }
void void
destroyHTable(Table ht) destroyHTable(Table ht)
{ GET_LD {
#ifdef O_PLMT #ifdef O_PLMT
if ( ht->mutex ) if ( ht->mutex )
{ simpleMutexDelete(ht->mutex); { simpleMutexDelete(ht->mutex);
@ -107,19 +105,19 @@ destroyHTable(Table ht)
} }
#if O_DEBUG || O_HASHSTAT #if O_DEBUG
#define HASHSTAT(c) c
static int lookups; static int lookups;
static int cmps; static int cmps;
void void
exitTables(int status, void *arg) exitTables(int status, void *arg)
{ Sdprintf("hashstat: Anonymous tables: %d lookups using %d compares\n", { (void)status;
(void)arg;
Sdprintf("hashstat: Anonymous tables: %d lookups using %d compares\n",
lookups, cmps); lookups, cmps);
} }
#else #endif
#define HASHSTAT(c)
#endif /*O_DEBUG*/
void void
@ -129,7 +127,7 @@ initTables(void)
if ( !done ) if ( !done )
{ done = TRUE; { done = TRUE;
HASHSTAT(PL_on_halt(exitTables, NULL)); DEBUG(MSG_HASH_STAT, PL_on_halt(exitTables, NULL));
} }
} }
@ -138,9 +136,9 @@ Symbol
lookupHTable(Table ht, void *name) lookupHTable(Table ht, void *name)
{ Symbol s = ht->entries[pointerHashValue(name, ht->buckets)]; { Symbol s = ht->entries[pointerHashValue(name, ht->buckets)];
HASHSTAT(lookups++); DEBUG(MSG_HASH_STAT, lookups++);
for( ; s; s = s->next) for( ; s; s = s->next)
{ HASHSTAT(cmps++); { DEBUG(MSG_HASH_STAT, cmps++);
if ( s->name == name ) if ( s->name == name )
return s; return s;
} }
@ -170,41 +168,75 @@ checkHTable(Table ht)
/* MT: Locked by calling addHTable() /* MT: Locked by calling addHTable()
*/ */
static void static Symbol
rehashHTable(Table ht) rehashHTable(Table ht, Symbol map)
{ GET_LD { Symbol *newentries, *oldentries;
Symbol *oldtab; int newbuckets, oldbuckets;
int oldbucks;
int i; int i;
int safe_copy = (ht->mutex != NULL);
oldtab = ht->entries; newbuckets = ht->buckets*2;
oldbucks = ht->buckets; newentries = allocHTableEntries(newbuckets);
ht->buckets *= 2;
allocHTableEntries(ht);
DEBUG(1, Sdprintf("Rehashing table %p to %d entries\n", ht, ht->buckets)); DEBUG(MSG_HASH_STAT,
Sdprintf("Rehashing table %p to %d entries\n", ht, ht->buckets));
for(i=0; i<oldbucks; i++) for(i=0; i<ht->buckets; i++)
{ Symbol s, n; { Symbol s, n;
for(s=oldtab[i]; s; s = n) if ( safe_copy )
{ int v = (int)pointerHashValue(s->name, ht->buckets); { for(s=ht->entries[i]; s; s = n)
{ int v = (int)pointerHashValue(s->name, newbuckets);
Symbol s2 = allocHeapOrHalt(sizeof(*s2));
n = s->next; n = s->next;
s->next = ht->entries[v]; if ( s == map )
ht->entries[v] = s; map = s2;
*s2 = *s;
s2->next = newentries[v];
newentries[v] = s2;
}
} else
{ for(s=ht->entries[i]; s; s = n)
{ int v = (int)pointerHashValue(s->name, newbuckets);
n = s->next;
s->next = newentries[v];
newentries[v] = s;
}
} }
} }
freeHeap(oldtab, oldbucks * sizeof(Symbol)); oldentries = ht->entries;
DEBUG(0, checkHTable(ht)); oldbuckets = ht->buckets;
ht->entries = newentries;
ht->buckets = newbuckets;
if ( safe_copy )
{ /* Here we should be waiting until */
/* active lookup are finished */
for(i=0; i<oldbuckets; i++)
{ Symbol s, n;
for(s=oldentries[i]; s; s = n)
{ n = s->next;
s->next = NULL; /* that causes old readers to stop */
freeHeap(s, sizeof(*s));
}
}
}
freeHeap(oldentries, oldbuckets * sizeof(Symbol));
DEBUG(CHK_SECURE, checkHTable(ht));
return map;
} }
Symbol Symbol
addHTable(Table ht, void *name, void *value) addHTable(Table ht, void *name, void *value)
{ GET_LD { Symbol s;
Symbol s;
int v; int v;
LOCK_TABLE(ht); LOCK_TABLE(ht);
@ -213,7 +245,7 @@ addHTable(Table ht, void *name, void *value)
{ UNLOCK_TABLE(ht); { UNLOCK_TABLE(ht);
return NULL; return NULL;
} }
s = allocHeap(sizeof(struct symbol)); s = allocHeapOrHalt(sizeof(struct symbol));
s->name = name; s->name = name;
s->value = value; s->value = value;
s->next = ht->entries[v]; s->next = ht->entries[v];
@ -223,7 +255,7 @@ addHTable(Table ht, void *name, void *value)
ht, name, value, ht->size)); ht, name, value, ht->size));
if ( ht->buckets * 2 < ht->size && !ht->enumerators ) if ( ht->buckets * 2 < ht->size && !ht->enumerators )
rehashHTable(ht); s = rehashHTable(ht, s);
UNLOCK_TABLE(ht); UNLOCK_TABLE(ht);
DEBUG(1, checkHTable(ht)); DEBUG(1, checkHTable(ht));
@ -237,8 +269,7 @@ Note: s must be in the table!
void void
deleteSymbolHTable(Table ht, Symbol s) deleteSymbolHTable(Table ht, Symbol s)
{ GET_LD { int v;
int v;
Symbol *h; Symbol *h;
TableEnum e; TableEnum e;
@ -255,6 +286,9 @@ deleteSymbolHTable(Table ht, Symbol s)
{ if ( *h == s ) { if ( *h == s )
{ *h = (*h)->next; { *h = (*h)->next;
s->next = NULL; /* force crash */
s->name = NULL;
s->value = NULL;
freeHeap(s, sizeof(struct symbol)); freeHeap(s, sizeof(struct symbol));
ht->size--; ht->size--;
@ -268,8 +302,7 @@ deleteSymbolHTable(Table ht, Symbol s)
void void
clearHTable(Table ht) clearHTable(Table ht)
{ GET_LD { int n;
int n;
TableEnum e; TableEnum e;
LOCK_TABLE(ht); LOCK_TABLE(ht);
@ -309,24 +342,23 @@ Table copyHTable(Table org)
Table Table
copyHTable(Table org) copyHTable(Table org)
{ GET_LD { Table ht;
Table ht;
int n; int n;
ht = allocHeap(sizeof(struct table)); ht = allocHeapOrHalt(sizeof(struct table));
LOCK_TABLE(org); LOCK_TABLE(org);
*ht = *org; /* copy all attributes */ *ht = *org; /* copy all attributes */
#ifdef O_PLMT #ifdef O_PLMT
ht->mutex = NULL; ht->mutex = NULL;
#endif #endif
allocHTableEntries(ht); ht->entries = allocHTableEntries(ht->buckets);
for(n=0; n < ht->buckets; n++) for(n=0; n < ht->buckets; n++)
{ Symbol s, *q; { Symbol s, *q;
q = &ht->entries[n]; q = &ht->entries[n];
for(s = org->entries[n]; s; s = s->next) for(s = org->entries[n]; s; s = s->next)
{ Symbol s2 = allocHeap(sizeof(*s2)); { Symbol s2 = allocHeapOrHalt(sizeof(*s2));
*q = s2; *q = s2;
q = &s2->next; q = &s2->next;
@ -340,7 +372,7 @@ copyHTable(Table org)
} }
#ifdef O_PLMT #ifdef O_PLMT
if ( org->mutex ) if ( org->mutex )
{ ht->mutex = allocHeap(sizeof(simpleMutex)); { ht->mutex = allocHeapOrHalt(sizeof(simpleMutex));
simpleMutexInit(ht->mutex); simpleMutexInit(ht->mutex);
} }
#endif #endif
@ -356,8 +388,7 @@ copyHTable(Table org)
TableEnum TableEnum
newTableEnum(Table ht) newTableEnum(Table ht)
{ GET_LD { TableEnum e = allocHeapOrHalt(sizeof(struct table_enum));
TableEnum e = allocHeap(sizeof(struct table_enum));
Symbol n; Symbol n;
LOCK_TABLE(ht); LOCK_TABLE(ht);
@ -378,8 +409,7 @@ newTableEnum(Table ht)
void void
freeTableEnum(TableEnum e) freeTableEnum(TableEnum e)
{ GET_LD { TableEnum *ep;
TableEnum *ep;
Table ht; Table ht;
if ( !e ) if ( !e )

View File

@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <string.h> /* get size_t */ #include <string.h> /* get size_t */