diff --git a/C/c_interface.c b/C/c_interface.c index fe3e462b7..2f2effe48 100644 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -356,6 +356,9 @@ #include "cut_c.h" #endif /* CUT_C */ +#if !HAVE_STRNCPY +#define strncpy(X,Y,Z) strcpy(X,Y) +#endif #define YAP_BOOT_FROM_PROLOG 0 #define YAP_BOOT_FROM_SAVED_CODE 1 @@ -2382,3 +2385,17 @@ YAP_AGCRegisterHook(Agc_hook hook) return old; } +X_API char * +YAP_cwd(void) +{ + char *buf; + int len; + if (!Yap_getcwd(Yap_FileNameBuf, YAP_FILENAME_MAX)) + return FALSE; + len = strlen(Yap_FileNameBuf); + buf = malloc(+1); + if (!buf) + return NULL; + strncpy(buf, Yap_FileNameBuf, len); + return buf; +} diff --git a/C/compiler.c b/C/compiler.c index a412fa9a6..0f122ea34 100644 --- a/C/compiler.c +++ b/C/compiler.c @@ -871,11 +871,17 @@ c_eq(Term t1, Term t2, compiler_struct *cglobs) } } /* first argument is an unbound var */ - c_var(t1, 0, 0, 0, cglobs); - cglobs->onhead = TRUE; + if (IsNewVar(t1)) { + c_var(t1, 0, 0, 0, cglobs); + } else { + c_var(t1, 0, 0, 0, cglobs); + cglobs->onhead = TRUE; + } if (IsVarTerm(t2)) { + cglobs->onhead = TRUE; c_var(t2, 0, 0, 0, cglobs); } else { + cglobs->onhead = TRUE; c_arg(0, t2, 0, 0, cglobs); } cglobs->onhead = FALSE; diff --git a/C/iopreds.c b/C/iopreds.c index cfd17406f..4e407a246 100644 --- a/C/iopreds.c +++ b/C/iopreds.c @@ -672,7 +672,7 @@ Yap_DebugGetc() curfile = NULL; } if (curfile == NULL) - YP_fgets(my_line, 200, stdin); + (void)YP_fgets(my_line, 200, stdin); eolflg = 0; lp = my_line; } diff --git a/C/sysbits.c b/C/sysbits.c index 2def99659..23de1c0d0 100644 --- a/C/sysbits.c +++ b/C/sysbits.c @@ -1608,6 +1608,34 @@ Yap_volume_header(char *file) return volume_header(file); } + +int Yap_getcwd(const char *buf, int len) +{ +#if __simplescalar__ + /* does not implement getcwd */ + strncpy(Yap_buf,yap_pwd,len); +#elif HAVE_GETCWD + if (getcwd ((char *)buf, len) == NULL) { +#if HAVE_STRERROR + Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "%s in getcwd/1", strerror(errno)); +#else + Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "error %d in getcwd/1", errno); +#endif + return FALSE; + } +#else + if (getwd (buf) == NULL) { +#if HAVE_STRERROR + Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "%s in getcwd/1", strerror(errno)); +#else + Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "in getcwd/1"); +#endif + return FALSE; + } +#endif + return TRUE; +} + /****** TODO: rewrite to use wordexp ****/ @@ -1698,16 +1726,8 @@ TrueFileName (char *source, char *root, char *result, int in_lib) #endif /* step 3: get the full file name */ if (!dir_separator(result[0]) && !volume_header(result)) { -#if __simplescalar__ - /* does not implement getcwd */ - strncpy(ares1,yap_pwd,YAP_FILENAME_MAX); -#elif HAVE_GETCWD - if (getcwd (ares1, YAP_FILENAME_MAX) == NULL) + if (!Yap_getcwd(ares1, YAP_FILENAME_MAX)) return FALSE; -#else - if (getwd (ares1) == NULL) - return FALSE; -#endif #if _MSC_VER || defined(__MINGW32__) strncat (ares1, "\\", YAP_FILENAME_MAX); #else @@ -1858,32 +1878,11 @@ p_true_file_name3 (void) return Yap_unify(ARG3, MkAtomTerm(Yap_LookupAtom(Yap_FileNameBuf))); } - static Int p_getcwd(void) { -#if __simplescalar__ - /* does not implement getcwd */ - strncpy(Yap_FileNameBuf,yap_pwd,YAP_FILENAME_MAX); -#elif HAVE_GETCWD - if (getcwd (Yap_FileNameBuf, YAP_FILENAME_MAX) == NULL) { -#if HAVE_STRERROR - Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "%s in getcwd/1", strerror(errno)); -#else - Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "error %d in getcwd/1", errno); -#endif + if (!Yap_getcwd(Yap_FileNameBuf, YAP_FILENAME_MAX)) return FALSE; - } -#else - if (getwd (Yap_FileNameBuf) == NULL) { -#if HAVE_STRERROR - Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "%s in getcwd/1", strerror(errno)); -#else - Yap_Error(OPERATING_SYSTEM_ERROR, ARG1, "in getcwd/1"); -#endif - return FALSE; - } -#endif return Yap_unify(ARG1,MkAtomTerm(Yap_LookupAtom(Yap_FileNameBuf))); } diff --git a/H/Yapproto.h b/H/Yapproto.h index ed59d062c..87efdff6d 100644 --- a/H/Yapproto.h +++ b/H/Yapproto.h @@ -314,6 +314,7 @@ void STD_PROTO(Yap_InitSysPath,(void)); void STD_PROTO(Yap_SetTextFile,(char *)); #endif void STD_PROTO(Yap_cputime_interval,(Int *,Int *)); +int STD_PROTO(Yap_getcwd,(const char *, int)); void STD_PROTO(Yap_walltime_interval,(Int *,Int *)); void STD_PROTO(Yap_InitSysbits,(void)); void STD_PROTO(Yap_InitSysPreds,(void)); diff --git a/include/SWI-Prolog.h b/include/SWI-Prolog.h index 7315bec54..8123349ae 100644 --- a/include/SWI-Prolog.h +++ b/include/SWI-Prolog.h @@ -307,8 +307,27 @@ extern X_API void PL_free(void *); #define PL_register_foreign(name, arity, function, flags) PL_register_foreign_in_module(NULL, (name), (arity), (function), (flags)) -extern X_API int Sprintf(char *,...); -extern X_API int Sdprintf(char *,...); +extern X_API int Sprintf(const char * fm,...); +extern X_API int Sdprintf(const char *,...); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Output representation for PL_get_chars() and friends. The +prepresentation type REP_FN is for PL_get_file_name() and friends. On +Windows we use UTF-8 which is translated by the `XOS' layer to Windows +UNICODE file functions. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +#define REP_ISO_LATIN_1 0x0000 /* output representation */ +#define REP_UTF8 0x1000 +#define REP_MB 0x2000 +#ifdef __WINDOWS__ +#define REP_FN REP_UTF8 +#else +#define REP_FN REP_MB +#endif + +#define PL_DIFF_LIST 0x20000 /* PL_unify_chars() */ + #ifdef SIO_MAGIC /* defined from */ extern X_API int PL_unify_stream(term_t t, IOSTREAM *s); @@ -316,6 +335,8 @@ extern X_API int PL_open_stream(term_t t, IOSTREAM *s); /* compat */ extern X_API int PL_get_stream_handle(term_t t, IOSTREAM **s); #endif +extern X_API char *PL_cwd(void); + void swi_install(void); #endif /* _FLI_H_INCLUDED */ diff --git a/include/YapInterface.h b/include/YapInterface.h index afe763264..b6d2c3d7f 100644 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -451,6 +451,9 @@ extern X_API int PROTO(YAP_AtomReleaseHold,(YAP_Atom)); /* void YAP_AtomReleaseHold(YAP_Atom) */ extern X_API YAP_agc_hook PROTO(YAP_AGCRegisterHook,(YAP_agc_hook)); +/* char *YAP_cwd(void) */ +extern X_API char * PROTO(YAP_cwd,(void)); + /* thread stuff */ extern X_API int PROTO(YAP_ThreadSelf,(void)); extern X_API YAP_CELL PROTO(YAP_ThreadCreateEngine,(YAP_thread_attr *)); diff --git a/library/yap2swi/yap2swi.c b/library/yap2swi/yap2swi.c index 17a944211..8bda127f3 100644 --- a/library/yap2swi/yap2swi.c +++ b/library/yap2swi/yap2swi.c @@ -1675,46 +1675,10 @@ PL_free(void *obj) return YAP_FreeSpaceFromYap(obj); } - -/* note: fprintf may be called from anywhere, so please don't try - to be smart and allocate stack from somewhere else */ -X_API int Sprintf(char *format,...) +X_API char * +PL_cwd(void) { - va_list ap; - char buf[512]; - - va_start(ap,format); -#ifdef HAVE_VSNPRINTF - vsnprintf(buf,512,format,ap); -#else - vsprintf(buf,format,ap); -#endif - va_end(ap); - - fputs(buf, stderr); - return 1; -} - - -/* note: fprintf may be called from anywhere, so please don't try - to be smart and allocate stack from somewhere else */ -X_API int Sdprintf(char *format,...) -{ - va_list ap; - char buf[512]; - - va_start(ap,format); -#ifdef HAVE_VSNPRINTF - vsnprintf(buf,512,format,ap); -#else - vsprintf(buf,format,ap); -#endif - va_end(ap); - -#if DEBUG - fputs(buf, stderr); -#endif - return 1; + return YAP_cwd(); } static int @@ -1738,1068 +1702,6 @@ SWI_ctime(void) #endif } -/***** SWI IO ***************/ - -#include - -#define char_to_int(c) (0xff & (int)(c)) - -struct { - struct { - IOSTREAM *streams[6]; - } IO; -} lds; - -#define LD (&lds) - -#define ARG_LD -#define GET_LD -#define PASS_LD - -#define LOCK() -#define UNLOCK() -#define FUNCTOR_dstream1 (functor_t)YAP_MkFunctor(YAP_LookupAtom("stream"),1) -#define succeed return 1 -#define fail return 0 - -static int S__removebuf(IOSTREAM *s); -static int S__flushbuf(IOSTREAM *s); - -#ifndef MB_LEN_MAX -#define MB_LEN_MAX 6 -#endif - - -#ifndef UTF8_H_INCLUDED -#define UTF8_H_INCLUDED - -#define UTF8_MALFORMED_REPLACEMENT 0xfffd - -#define ISUTF8_MB(c) ((unsigned)(c) >= 0xc0 && (unsigned)(c) <= 0xfd) - -#define ISUTF8_CB(c) (((c)&0xc0) == 0x80) /* Is continuation byte */ -#define ISUTF8_FB2(c) (((c)&0xe0) == 0xc0) -#define ISUTF8_FB3(c) (((c)&0xf0) == 0xe0) -#define ISUTF8_FB4(c) (((c)&0xf8) == 0xf0) -#define ISUTF8_FB5(c) (((c)&0xfc) == 0xf8) -#define ISUTF8_FB6(c) (((c)&0xfe) == 0xfc) - -#define UTF8_FBN(c) (!(c&0x80) ? 0 : \ - ISUTF8_FB2(c) ? 1 : \ - ISUTF8_FB3(c) ? 2 : \ - ISUTF8_FB4(c) ? 3 : \ - ISUTF8_FB5(c) ? 4 : \ - ISUTF8_FB6(c) ? 5 : -1) -#define UTF8_FBV(c,n) ( n == 0 ? c : (c & ((0x01<<(6-n))-1)) ) - -#define utf8_get_char(in, chr) \ - (*(in) & 0x80 ? _PL__utf8_get_char(in, chr) \ - : (*(chr) = *(in), (char *)(in)+1)) -#define utf8_put_char(out, chr) \ - ((chr) < 0x80 ? out[0]=(char)(chr), out+1 \ - : _PL__utf8_put_char(out, (chr))) - -extern char *_PL__utf8_get_char(const char *in, int *chr); -extern char *_PL__utf8_put_char(char *out, int chr); - -extern unsigned int utf8_strlen(const char *s, unsigned int len); - -#endif /*UTF8_H_INCLUDED*/ - -typedef struct symbol * Symbol; /* symbol of hash table */ - -struct symbol -{ Symbol next; /* next in chain */ - void * name; /* name entry of symbol */ - void * value; /* associated value with name */ -}; - -static Symbol *streamContext; - -static Symbol *streamAliases; - -#define NULL_ATOM 0L - -#define allocHeap(size) YAP_AllocSpaceFromYap(size) - -// FIX THIS -#define PL_error(A,B,C,D,E,F) 0 - -static Symbol lookupHTable(Symbol *htp, void *name) -{ - Symbol ht = *htp; - while (ht) { - if (ht->name == name) return ht; - } - return NULL; -} - -static void addHTable(Symbol *htp, void *name, void *val) -{ - Symbol s = (Symbol)allocHeap(sizeof(Symbol)); - if (!s) - return; - s->next = *htp; - s->name = name; - s->value = val; - *htp = s; -} - -typedef struct _alias -{ struct _alias *next; - atom_t name; -} alias; - -typedef struct -{ alias *alias_head; - alias *alias_tail; - atom_t filename; /* associated filename */ - unsigned flags; -} stream_context; - - -static stream_context * -getStreamContext(IOSTREAM *s) -{ Symbol symb; - - if ( !(symb = lookupHTable(streamContext, s)) ) - { GET_LD - stream_context *ctx = allocHeap(sizeof(*ctx)); - - // DEBUG(1, Sdprintf("Created ctx=%p for stream %p\n", ctx, s)); - - ctx->alias_head = ctx->alias_tail = NULL; - ctx->filename = NULL_ATOM; - ctx->flags = 0; - addHTable(streamContext, s, ctx); - - return ctx; - } - - return symb->value; -} - -char * -_PL__utf8_put_char(char *out, int chr) -{ if ( chr < 0x80 ) - { *out++ = chr; - } else if ( chr < 0x800 ) - { *out++ = 0xc0|((chr>>6)&0x1f); - *out++ = 0x80|(chr&0x3f); - } else if ( chr < 0x10000 ) - { *out++ = 0xe0|((chr>>12)&0x0f); - *out++ = 0x80|((chr>>6)&0x3f); - *out++ = 0x80|(chr&0x3f); - } else if ( chr < 0x200000 ) - { *out++ = 0xf0|((chr>>18)&0x07); - *out++ = 0x80|((chr>>12)&0x3f); - *out++ = 0x80|((chr>>6)&0x3f); - *out++ = 0x80|(chr&0x3f); - } else if ( chr < 0x4000000 ) - { *out++ = 0xf8|((chr>>24)&0x03); - *out++ = 0x80|((chr>>18)&0x3f); - *out++ = 0x80|((chr>>12)&0x3f); - *out++ = 0x80|((chr>>6)&0x3f); - *out++ = 0x80|(chr&0x3f); - } else if ( chr < 0x80000000 ) - { *out++ = 0xfc|((chr>>30)&0x01); - *out++ = 0x80|((chr>>24)&0x3f); - *out++ = 0x80|((chr>>18)&0x3f); - *out++ = 0x80|((chr>>12)&0x3f); - *out++ = 0x80|((chr>>6)&0x3f); - *out++ = 0x80|(chr&0x3f); - } - - return out; -} - - -static inline void -update_linepos(IOSTREAM *s, int c) -{ IOPOS *p = s->position; - - switch(c) - { case '\n': - p->lineno++; - p->linepos = 0; - s->flags &= ~SIO_NOLINEPOS; -#ifdef __WIN32__ - if ( s->flags & O_TEXT ) - p->charno++; /* writes one extra! */ -#endif - break; - case '\r': - p->linepos = 0; - s->flags &= ~SIO_NOLINEPOS; - break; - case '\b': - if ( p->linepos > 0 ) - p->linepos--; - break; - case EOF: - break; - case '\t': - p->linepos |= 7; - default: - p->linepos++; - } -} - - - - - /******************************* - * BUFFER * - *******************************/ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Note that the buffer is allocated from s->unbuffer, which starts -MB_LEN_MAX before s->buffer, so we can always push-back a wide character -into a multibyte stream. We do not do this for SIO_USERBUF case, but -this is only used by the output stream Svfprintf() where it is not -needed. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -static int -S__setbuf(IOSTREAM *s, char *buffer, int size) -{ if ( size == 0 ) - size = SIO_BUFSIZE; - - S__removebuf(s); - s->bufsize = size; - - if ( buffer ) - { s->unbuffer = s->buffer = buffer; - s->flags |= SIO_USERBUF; - } else - { if ( !(s->unbuffer = malloc(s->bufsize+MB_LEN_MAX)) ) - { errno = ENOMEM; - return -1; - } - s->flags &= ~SIO_USERBUF; - s->buffer = s->unbuffer + MB_LEN_MAX; - } - - s->limitp = &s->buffer[s->bufsize]; - s->bufp = s->buffer; - - return size; -} - - -static int -S__removebuf(IOSTREAM *s) -{ if ( s->buffer && s->unbuffer ) - { int rval = 0; - - if ( (s->flags & SIO_OUTPUT) && S__flushbuf(s) < 0 ) - rval = -1; - - if ( !(s->flags & SIO_USERBUF) ) - free(s->unbuffer); - s->bufp = s->limitp = s->buffer = s->unbuffer = NULL; - s->bufsize = 0; - - return rval; - } - - return 0; -} - - -#ifdef DEBUG_IO_LOCKS -static char * -Sname(IOSTREAM *s) -{ if ( s == Serror ) return "error"; - if ( s == Sinput ) return "input"; - if ( s == Soutput ) return "output"; - return "?"; -} -#endif - - /******************************* - * FLUSH/FILL * - *******************************/ - -static int -S__flushbuf(IOSTREAM *s) -{ int size; - char *from = s->buffer; - - while ( (size = s->bufp - from) > 0 ) - { int n = (*s->functions->write)(s->handle, from, size); - - if ( n > 0 ) /* wrote some */ - { from += n; - } else if ( n < 0 ) /* error */ - { s->flags |= SIO_FERR; - return -1; - } else /* wrote nothing? */ - { break; - } - } - - if ( s->bufp - from == 0 ) /* full flush */ - { int rc = s->bufp - s->buffer; - - s->bufp = s->buffer; - - return rc; - } else /* partial flush */ - { int rc = from - s->buffer; - int left = s->bufp - from; - - memmove(s->buffer, from, left); - s->bufp = s->buffer + left; - - return rc; - } -} - - -static inline int -S__updatefilepos(IOSTREAM *s, int c) -{ IOPOS *p = s->position; - - if ( p ) - { update_linepos(s, c); - p->charno++; - } - - return c; -} - - -int -Sfileno(IOSTREAM *s) -{ int n; - - if ( s->flags & SIO_FILE ) - { long h = (long)s->handle; - n = (int)h; - } else if ( s->flags & SIO_PIPE ) - { n = fileno((FILE *)s->handle); - } else if ( s->functions->control && - (*s->functions->control)(s->handle, - SIO_GETFILENO, - (void *)&n) == 0 ) - { ; - } else - { errno = EINVAL; - n = -1; /* no file stream */ - } - - return n; -} - - -IOSTREAM * -Snew(void *handle, int flags, IOFUNCTIONS *functions) -{ IOSTREAM *s; - int fd; - - if ( !(s = malloc(sizeof(IOSTREAM))) ) - { errno = ENOMEM; - return NULL; - } - memset((char *)s, 0, sizeof(IOSTREAM)); - s->magic = SIO_MAGIC; - s->lastc = EOF; - s->flags = flags; - s->handle = handle; - s->functions = functions; - s->timeout = -1; /* infinite */ - s->posbuf.lineno = 1; - s->encoding = ENC_ISO_LATIN_1; - if ( flags & SIO_RECORDPOS ) - s->position = &s->posbuf; -#ifdef O_PLMT - if ( !(flags & SIO_NOMUTEX) ) - { if ( !(s->mutex = malloc(sizeof(recursiveMutex))) ) - { free(s); - return NULL; - } - recursiveMutexInit(s->mutex); - } -#endif - if ( (fd = Sfileno(s)) >= 0 && isatty(fd) ) - s->flags |= SIO_ISATTY; - - return s; -} - - -X_API int -PL_unify_stream(term_t t, IOSTREAM *s) -{ GET_LD - stream_context *ctx; - term_t a = PL_new_term_ref(); - - LOCK(); - ctx = getStreamContext(s); - UNLOCK(); - - PL_put_pointer(a, s); - PL_cons_functor(a, FUNCTOR_dstream1, a); - - if ( PL_unify(t, a) ) - succeed; - if ( PL_is_functor(t, FUNCTOR_dstream1) ) - fail; - - return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_stream, t); -} - -int /* old FLI name (compatibility) */ -PL_open_stream(term_t handle, IOSTREAM *s) -{ return PL_unify_stream(handle, s); -} - -#define SH_ERRORS 0x01 /* generate errors */ -#define SH_ALIAS 0x02 /* allow alias */ -#define SH_UNLOCKED 0x04 /* don't lock the stream */ -#define SH_SAFE 0x08 /* Lookup in table */ - -#define _PL_get_arg PL_get_arg - -#define getStream(s) (s) - -static int -get_stream_handle__LD(term_t t, IOSTREAM **s, int flags ARG_LD) -{ atom_t alias; - - if ( PL_is_functor(t, FUNCTOR_dstream1) ) - { void *p; - term_t a = PL_new_term_ref(); - - _PL_get_arg(1, t, a); - if ( PL_get_pointer(a, &p) ) - { if ( flags & SH_SAFE ) - { Symbol symb; - - LOCK(); - symb = lookupHTable(streamContext, p); - UNLOCK(); - - if ( !symb ) - goto noent; - } - - if ( flags & SH_UNLOCKED ) - { if ( ((IOSTREAM *)p)->magic == SIO_MAGIC ) - { *s = p; - return TRUE; - } - goto noent; - } - - if ( (*s = getStream(p)) ) - return TRUE; - - goto noent; - } - } else if ( PL_get_atom(t, &alias) ) - { Symbol symb; - - if ( !(flags & SH_UNLOCKED) ) - LOCK(); - if ( (symb=lookupHTable(streamAliases, (void *)alias)) ) - { IOSTREAM *stream; - unsigned long n = (unsigned long)symb->value; - - if ( n < 6 ) /* standard stream! */ - { stream = LD->IO.streams[n]; - } else - stream = symb->value; - - if ( !(flags & SH_UNLOCKED) ) - UNLOCK(); - - if ( stream ) - { if ( (flags & SH_UNLOCKED) ) - { if ( stream->magic == SIO_MAGIC ) - { *s = stream; - return TRUE; - } - } else if ( (*s = getStream(stream)) ) - return TRUE; - goto noent; - } - } - if ( !(flags & SH_UNLOCKED) ) - UNLOCK(); - - goto noent; - } - - if ( flags & SH_ERRORS ) - return PL_error(NULL, 0, NULL, ERR_DOMAIN, - (flags&SH_ALIAS) ? ATOM_stream_or_alias : ATOM_stream, t); - - fail; - -noent: - if ( flags & SH_ERRORS ) - PL_error(NULL, 0, NULL, ERR_EXISTENCE, ATOM_stream, t); - fail; -} - -#define get_stream_handle(t, sp, flags) \ - get_stream_handle__LD(t, sp, flags PASS_LD) - -int -PL_get_stream_handle(term_t t, IOSTREAM **s) -{ GET_LD - return get_stream_handle(t, s, SH_ERRORS|SH_ALIAS); -} - -static inline int -get_byte(IOSTREAM *s) -{ int c = Snpgetc(s); - - if ( s->position ) - s->position->byteno++; - - return c; -} - - -int -Sgetcode(IOSTREAM *s) -{ int c; - -#ifdef CRLF_MAPPING -retry: -#endif - - switch(s->encoding) - { case ENC_OCTET: - case ENC_ISO_LATIN_1: - c = get_byte(s); - break; - case ENC_ASCII: - { c = get_byte(s); - if ( c > 128 ) - Sseterr(s, SIO_WARN, "non-ASCII character"); - break; - } - case ENC_ANSI: - { char b[1]; - int rc, n = 0; - wchar_t wc; - - if ( !s->mbstate ) - { if ( !(s->mbstate = malloc(sizeof(*s->mbstate))) ) - return EOF; /* out of memory */ - memset(s->mbstate, 0, sizeof(*s->mbstate)); - } - - for(;;) - { if ( (c = get_byte(s)) == EOF ) - { if ( n == 0 ) - return EOF; - else - { Sseterr(s, SIO_WARN, "EOF in multibyte Sequence"); - goto mberr; - } - } - b[0] = c; - - if ( (rc=mbrtowc(&wc, b, 1, s->mbstate)) == 1 ) - { c = wc; - goto out; - } else if ( rc == -1 ) - { Sseterr(s, SIO_WARN, "Illegal multibyte Sequence"); - goto mberr; - } /* else -2: incomplete */ - } - - mberr: - c = UTF8_MALFORMED_REPLACEMENT; - goto out; - } - case ENC_UTF8: - { c = get_byte(s); - if ( c == EOF ) - break; - - if ( c & 0x80 ) - { int extra = UTF8_FBN(c); - int code; - - code = UTF8_FBV(c,extra); - for( ; extra > 0; extra-- ) - { int c2 = get_byte(s); - - if ( !ISUTF8_CB(c2) ) - { Sseterr(s, SIO_WARN, "Illegal UTF-8 Sequence"); - c = UTF8_MALFORMED_REPLACEMENT; - Sungetc(c2, s); - goto out; - } - code = (code<<6)+(c2&0x3f); - } - c = code; - } - break; - } - case ENC_UNICODE_BE: - case ENC_UNICODE_LE: - { int c1, c2; - - c1 = get_byte(s); - if ( c1 == EOF ) - return EOF; - c2 = get_byte(s); - - if ( c2 == EOF ) - { Sseterr(s, SIO_WARN, "EOF in unicode character"); - c = UTF8_MALFORMED_REPLACEMENT; - } else - { if ( s->encoding == ENC_UNICODE_BE ) - c = (c1<<8)+c2; - else - c = (c2<<8)+c1; - } - - break; - } - case ENC_WCHAR: - { pl_wchar_t chr; - char *p = (char*)&chr; - int n; - - for(n=0; nflags&SIO_TEXT) ) - goto retry; -#endif - - if ( s->tee && s->tee->magic == SIO_MAGIC && c != -1 ) - Sputcode(c, s->tee); - - return S__updatefilepos(s, c); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -S__fillbuf() fills the read-buffer, returning the first character of it. -It also realises the SWI-Prolog timeout facility. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -int -S__fillbuf(IOSTREAM *s) -{ int c; - - if ( s->flags & (SIO_FEOF|SIO_FERR) ) - { s->flags |= SIO_FEOF2; /* reading past eof */ - goto error; - } - -#ifdef HAVE_SELECT - s->flags &= ~SIO_TIMEOUT; - - if ( s->timeout >= 0 ) - { int fd = Sfileno(s); - - if ( fd >= 0 ) - { fd_set wait; - struct timeval time; - int rc; - - time.tv_sec = s->timeout / 1000; - time.tv_usec = (s->timeout % 1000) * 1000; - FD_ZERO(&wait); -#ifdef WIN32 - 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; - goto error; - } - - continue; - } - - break; - } - - if ( rc == 0 ) - { s->flags |= (SIO_TIMEOUT|SIO_FERR); - goto error; - } - } else - { errno = EPERM; /* no permission to select */ - s->flags |= SIO_FERR; - goto error; - } - } -#endif - - - if ( s->flags & SIO_NBUF ) - { char chr; - int n; - - if ( (n=(*s->functions->read)(s->handle, &chr, 1)) == 1 ) - { c = char_to_int(chr); - goto ok; - } else if ( n == 0 ) - { if ( !(s->flags & SIO_NOFEOF) ) - s->flags |= SIO_FEOF; - goto error; - } else - { s->flags |= SIO_FERR; - goto error; /* error */ - } - } else - { int n, len; - - if ( !s->buffer ) - { if ( S__setbuf(s, NULL, 0) < 0 ) - goto error; - s->bufp = s->limitp = s->buffer; - len = s->bufsize; - } else if ( s->bufp < s->limitp ) - { len = s->limitp - s->bufp; - memmove(s->buffer, s->bufp, s->limitp - s->bufp); - s->bufp = s->buffer; - s->limitp = &s->bufp[len]; - len = s->bufsize - len; - } else - { s->bufp = s->limitp = s->buffer; - len = s->bufsize; - } - - if ( (n=(*s->functions->read)(s->handle, s->limitp, len)) > 0 ) - { s->limitp += n; - c = char_to_int(*s->bufp++); - goto ok; - } else - { if ( n == 0 ) - { if ( !(s->flags & SIO_NOFEOF) ) - s->flags |= SIO_FEOF; - goto error; -#ifdef EWOULDBLOCK - } else if ( errno == EWOULDBLOCK ) - { s->bufp = s->buffer; - s->limitp = s->buffer; - goto error; -#endif - } else - { s->flags |= SIO_FERR; - goto error; - } - } - } - -error: - c = -1; -ok: - return c; -} - -static int -S__flushbufc(int c, IOSTREAM *s) -{ if ( s->buffer ) - { if ( S__flushbuf(s) <= 0 ) /* == 0: no progress!? */ - c = -1; - else - *s->bufp++ = (c & 0xff); - } else - { if ( s->flags & SIO_NBUF ) - { char chr = (char)c; - - if ( (*s->functions->write)(s->handle, &chr, 1) != 1 ) - { s->flags |= SIO_FERR; - c = -1; - } - } else - { if ( S__setbuf(s, NULL, 0) < 0 ) - { s->flags |= SIO_FERR; - c = -1; - } else - *s->bufp++ = (char)c; - } - } - - return c; -} - - -static inline void -unget_byte(int c, IOSTREAM *s) -{ IOPOS *p = s->position; - - *--s->bufp = c; - if ( p ) - { p->charno--; - p->byteno--; - s->flags |= (SIO_NOLINENO|SIO_NOLINEPOS); - } -} - - -int -Sungetc(int c, IOSTREAM *s) -{ if ( s->bufp > s->unbuffer ) - { unget_byte(c, s); - - return c; - } - - return -1; -} - -static int -put_byte(int c, IOSTREAM *s) -{ c &= 0xff; - - if ( s->bufp < s->limitp ) - { *s->bufp++ = c; - } else - { if ( S__flushbufc(c, s) < 0 ) - { s->lastc = EOF; - return -1; - } - } - - if ( s->position ) - s->position->byteno++; - - return c; -} - - -static int -reperror(int c, IOSTREAM *s) -{ if ( c >= 0 && (s->flags & (SIO_REPXML|SIO_REPPL)) ) - { char buf[16]; - const char *q; - - if ( (s->flags & SIO_REPPL) ) - { if ( c <= 0xffff ) - sprintf(buf, "\\u%04X", c); - else - sprintf(buf, "\\U%08X", c); - } else - sprintf(buf, "&#%d;", c); - - for(q = buf; *q; q++) - { if ( put_byte(*q, s) < 0 ) - return -1; - } - - return c; - } - - Sseterr(s, SIO_FERR|SIO_CLEARERR, "Encoding cannot represent character"); - return -1; -} - -int -Sputcode(int c, IOSTREAM *s) -{ if ( c < 0 ) - return reperror(c, s); - - if ( s->tee && s->tee->magic == SIO_MAGIC ) - Sputcode(c, s->tee); - -#ifdef CRLF_MAPPING - if ( c == '\n' && (s->flags&SIO_TEXT) ) - { if ( Sputcode('\r', s) < 0 ) - return -1; - } -#endif - - switch(s->encoding) - { case ENC_OCTET: - case ENC_ISO_LATIN_1: - if ( c >= 256 ) - { if ( reperror(c, s) < 0 ) - return -1; - break; - } - simple: - if ( put_byte(c, s) < 0 ) - return -1; - break; - case ENC_ASCII: - if ( c >= 128 ) - { if ( reperror(c, s) < 0 ) - return -1; - break; - } - goto simple; - case ENC_ANSI: - { char b[MB_LEN_MAX]; - int n; - - if ( !s->mbstate ) - { if ( !(s->mbstate = malloc(sizeof(*s->mbstate))) ) - return EOF; /* out of memory */ - memset(s->mbstate, 0, sizeof(*s->mbstate)); - } - - if ( (n = wcrtomb(b, (wchar_t)c, s->mbstate)) < 0 ) - { if ( reperror(c, s) < 0 ) - return -1; - } else - { int i; - - for(i=0; i>8, s) < 0 ) - return -1; - if ( put_byte(c&0xff, s) < 0 ) - return -1; - break; - case ENC_UNICODE_LE: - if ( put_byte(c&0xff, s) < 0 ) - return -1; - if ( put_byte(c>>8, s) < 0 ) - return -1; - break; - case ENC_WCHAR: - { pl_wchar_t chr = c; - unsigned char *q = (unsigned char *)&chr; - unsigned char *e = &q[sizeof(pl_wchar_t)]; - - while(qlastc = c; - - if ( c == '\n' && (s->flags & SIO_LBUF) ) - { if ( S__flushbuf(s) < 0 ) - return -1; - } - - return S__updatefilepos(s, c); -} - - - /******************************* - * FLAGS * - *******************************/ - -int -Sfeof(IOSTREAM *s) -{ if ( s->flags & SIO_FEOF ) - return TRUE; - - if ( s->bufp < s->limitp ) - return FALSE; - - if ( s->flags & SIO_NBUF ) - { errno = EINVAL; - return -1; - } - - if ( S__fillbuf(s) == -1 ) - return TRUE; - - s->bufp--; - return FALSE; -} - - -int -Sferror(IOSTREAM *s) -{ return (s->flags & SIO_FERR) != 0; -} - - -int -Sfpasteof(IOSTREAM *s) -{ return (s->flags & (SIO_FEOF2ERR|SIO_FEOF2)) == (SIO_FEOF2ERR|SIO_FEOF2); -} - - -void -Sclearerr(IOSTREAM *s) -{ s->flags &= ~(SIO_FEOF|SIO_WARN|SIO_FERR|SIO_FEOF2|SIO_TIMEOUT|SIO_CLEARERR); - Sseterr(s, 0, NULL); -} - - -void -Sseterr(IOSTREAM *s, int flag, const char *message) -{ if ( s->message ) - { free(s->message); - s->message = NULL; - s->flags &= ~SIO_CLEARERR; - } - if ( message ) - { s->flags |= flag; - s->message = strdup(message); - } else - { s->flags &= ~flag; - } -} - - void Yap_swi_install(void);