| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /*  Part of SWI-Prolog
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Author:        Jan Wielemaker | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     E-mail:        J.Wielemaker@cs.vu.nl | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     WWW:           http://www.swi-prolog.org
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     Copyright (C): 1985-2012, University of Amsterdam | 
					
						
							|  |  |  | 			      VU University Amsterdam | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |     modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |     License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |     version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |     Lesser General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |     License along with this library; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-24 15:32:29 +00:00
										 |  |  | /** @ingroup InputOutput
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | @{ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | This module is far too big.  It defines a layer around open(), etc.   to | 
					
						
							|  |  |  | get  opening  and  closing  of  files to the symbolic level required for | 
					
						
							|  |  |  | Prolog.  It also defines basic I/O  predicates,  stream  based  I/O  and | 
					
						
							|  |  |  | finally  a  bundle  of  operations  on  files,  such  as name expansion, | 
					
						
							|  |  |  | renaming, deleting, etc.  Most of this module is rather straightforward. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If time is there I will have a look at all this to  clean  it.   Notably | 
					
						
							|  |  |  | handling times must be cleaned, but that not only holds for this module. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*#define O_DEBUG 1*/ | 
					
						
							|  |  |  | /*#define O_DEBUG_MT 1*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | #define NEEDS_SWINSOCK
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #include "pl-incl.h"
 | 
					
						
							|  |  |  | #include "pl-ctype.h"
 | 
					
						
							|  |  |  | #include "pl-utf8.h"
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-28 02:34:26 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef HAVE_SYS_SELECT_H
 | 
					
						
							|  |  |  | #include <sys/select.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_TIME_H
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_PARAM_H
 | 
					
						
							|  |  |  | #include <sys/param.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_FILE_H
 | 
					
						
							|  |  |  | #include <sys/file.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_UNISTD_H
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #include <fcntl.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_BSTRING_H
 | 
					
						
							|  |  |  | #include <bstring.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-11-28 02:34:26 +00:00
										 |  |  | #if HAVE_ALLOCA_H
 | 
					
						
							|  |  |  | #include <alloca.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define LOCK()   PL_LOCK(L_FILE)	/* MT locking */
 | 
					
						
							|  |  |  | #define UNLOCK() PL_UNLOCK(L_FILE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | #undef LD				/* fetch LD once per function */
 | 
					
						
							|  |  |  | #define LD LOCAL_LD
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-02 23:19:39 +00:00
										 |  |  | /* there are two types of stream property functions. In the usual case,
 | 
					
						
							|  |  |  |    they have an argument, but in a few cases they don't */ | 
					
						
							|  |  |  | typedef int (*property0_t)(IOSTREAM *s ARG_LD); | 
					
						
							|  |  |  | typedef int (*property_t)(IOSTREAM *s, term_t prop ARG_LD); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | static int	bad_encoding(const char *msg, atom_t name); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int	noprotocol(void); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static PL_blob_t stream_blob; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-03 18:52:56 +01:00
										 |  |  | const atom_t standardStreams[] = | 
					
						
							|  |  |  | { ATOM_user_input,			/* 0 */ | 
					
						
							|  |  |  |   ATOM_user_output,			/* 1 */ | 
					
						
							|  |  |  |   ATOM_user_error,			/* 2 */ | 
					
						
							|  |  |  |   ATOM_current_input,			/* 3 */ | 
					
						
							|  |  |  |   ATOM_current_output,			/* 4 */ | 
					
						
							|  |  |  |   ATOM_protocol,			/* 5 */ | 
					
						
							|  |  |  |   NULL_ATOM | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | standardStreamIndexFromName(atom_t name) | 
					
						
							|  |  |  | { const atom_t *ap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(ap=standardStreams; *ap; ap++) | 
					
						
							|  |  |  |   { if ( *ap == name ) | 
					
						
							|  |  |  |       return (int)(ap - standardStreams); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | standardStreamIndexFromStream(IOSTREAM *s) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM **sp = LD->IO.streams; | 
					
						
							|  |  |  |   int i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for( ; i<6; i++, sp++ ) | 
					
						
							|  |  |  |   { if ( *sp == s ) | 
					
						
							|  |  |  |       return i; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	   BOOKKEEPING		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  |  * @defgroup StreamM Stream Manipulation | 
					
						
							|  |  |  |  * @ingroup InputOutput | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static void aliasStream(IOSTREAM *s, atom_t alias); | 
					
						
							|  |  |  | static void unaliasStream(IOSTREAM *s, atom_t name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Table streamAliases;		/* alias --> stream */ | 
					
						
							|  |  |  | static Table streamContext;		/* stream --> extra data */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _alias | 
					
						
							|  |  |  | { struct _alias *next; | 
					
						
							|  |  |  |   atom_t name; | 
					
						
							|  |  |  | } alias; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define IO_TELL	0x001			/* opened by tell/1 */
 | 
					
						
							|  |  |  | #define IO_SEE  0x002			/* opened by see/1 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { alias *alias_head; | 
					
						
							|  |  |  |   alias *alias_tail; | 
					
						
							|  |  |  |   atom_t filename;			/* associated filename */ | 
					
						
							|  |  |  |   unsigned flags; | 
					
						
							|  |  |  | } stream_context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static stream_context * | 
					
						
							|  |  |  | getStreamContext(IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { if ( !s->context ) | 
					
						
							|  |  |  |   { stream_context *ctx = allocHeapOrHalt(sizeof(*ctx)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     s->context = ctx; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   return (stream_context*)s->context; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static stream_context * | 
					
						
							|  |  |  | getExistingStreamContext(IOSTREAM *s) | 
					
						
							|  |  |  | { return (stream_context*)s->context; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /* MT: Must be called locked */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | aliasStream(IOSTREAM *s, atom_t name) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { stream_context *ctx; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Symbol symb; | 
					
						
							|  |  |  |   alias *a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* ensure name is free (error?) */ | 
					
						
							|  |  |  |   if ( (symb = lookupHTable(streamAliases, (void *)name)) ) | 
					
						
							|  |  |  |     unaliasStream(symb->value, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ctx = getStreamContext(s); | 
					
						
							|  |  |  |   addHTable(streamAliases, (void *)name, s); | 
					
						
							|  |  |  |   PL_register_atom(name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   a = allocHeapOrHalt(sizeof(*a)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   a->next = NULL; | 
					
						
							|  |  |  |   a->name = name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->alias_tail ) | 
					
						
							|  |  |  |   { ctx->alias_tail->next = a; | 
					
						
							|  |  |  |     ctx->alias_tail = a; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { ctx->alias_head = ctx->alias_tail = a; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* MT: Locked by freeStream()
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | unaliasStream(IOSTREAM *s, atom_t name) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { Symbol symb; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( name ) | 
					
						
							|  |  |  |   { if ( (symb = lookupHTable(streamAliases, (void *)name)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { stream_context *ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       deleteSymbolHTable(streamAliases, symb); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       if ( (ctx=getExistingStreamContext(s)) ) | 
					
						
							|  |  |  |       { alias **a; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(a = &ctx->alias_head; *a; a = &(*a)->next) | 
					
						
							|  |  |  | 	{ if ( (*a)->name == name ) | 
					
						
							|  |  |  | 	  { alias *tmp = *a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    *a = tmp->next; | 
					
						
							|  |  |  | 	    freeHeap(tmp, sizeof(*tmp)); | 
					
						
							|  |  |  | 	    if ( tmp == ctx->alias_tail ) | 
					
						
							|  |  |  | 	      ctx->alias_tail = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PL_unregister_atom(name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else				/* delete them all */ | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { stream_context *ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (ctx=getExistingStreamContext(s)) ) | 
					
						
							|  |  |  |     { alias *a, *n; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for(a = ctx->alias_head; a; a=n) | 
					
						
							|  |  |  |       { Symbol s2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = a->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( (s2 = lookupHTable(streamAliases, (void *)a->name)) ) | 
					
						
							|  |  |  | 	{ deleteSymbolHTable(streamAliases, s2); | 
					
						
							|  |  |  | 	  PL_unregister_atom(a->name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	freeHeap(a, sizeof(*a)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ctx->alias_head = ctx->alias_tail = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | freeStream(IOSTREAM *s) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   Symbol symb; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   IOSTREAM **sp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DEBUG(1, Sdprintf("freeStream(%p)\n", s)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK(); | 
					
						
							|  |  |  |   unaliasStream(s, NULL_ATOM); | 
					
						
							|  |  |  |   if ( (symb=lookupHTable(streamContext, s)) ) | 
					
						
							|  |  |  |   { stream_context *ctx = symb->value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     if ( ctx->filename != NULL_ATOM ) | 
					
						
							|  |  |  |     { PL_unregister_atom(ctx->filename); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( ctx->filename == source_file_name ) | 
					
						
							|  |  |  |       { source_file_name = NULL_ATOM;	/* TBD: pop? */ | 
					
						
							|  |  |  | 	source_line_no = -1; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     freeHeap(ctx, sizeof(*ctx)); | 
					
						
							|  |  |  |     deleteSymbolHTable(streamContext, symb); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 					/* if we are a standard stream */ | 
					
						
							|  |  |  | 					/* reassociate with standard I/O */ | 
					
						
							|  |  |  | 					/* NOTE: there may be more! */ | 
					
						
							|  |  |  |   for(i=0, sp = LD->IO.streams; i<6; i++, sp++) | 
					
						
							|  |  |  |   { if ( *sp == s ) | 
					
						
							|  |  |  |     { if ( s->flags & SIO_INPUT ) | 
					
						
							|  |  |  | 	*sp = Sinput; | 
					
						
							|  |  |  |       else if ( sp == &Suser_error ) | 
					
						
							|  |  |  | 	*sp = Serror; | 
					
						
							|  |  |  |       else if ( sp == &Sprotocol ) | 
					
						
							|  |  |  | 	*sp = NULL; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	*sp = Soutput; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   UNLOCK(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* MT: locked by caller (openStream()) */ | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | /* name must be registered by the caller */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | setFileNameStream_unlocked(IOSTREAM *s, atom_t name) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | { stream_context *ctx = getStreamContext(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->filename ) | 
					
						
							|  |  |  |   { PL_unregister_atom(ctx->filename); | 
					
						
							|  |  |  |     ctx->filename = NULL_ATOM; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !(name == NULL_ATOM || name == ATOM_) ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     ctx->filename = name; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | int | 
					
						
							|  |  |  | setFileNameStream(IOSTREAM *s, atom_t name) | 
					
						
							|  |  |  | { LOCK(); | 
					
						
							|  |  |  |   setFileNameStream_unlocked(s, name); | 
					
						
							|  |  |  |   PL_register_atom(name); | 
					
						
							|  |  |  |   UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | atom_t | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | fileNameStream(IOSTREAM *s) | 
					
						
							|  |  |  | { atom_t name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK(); | 
					
						
							|  |  |  |   name = getStreamContext(s)->filename; | 
					
						
							|  |  |  |   UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | #if __YAP_PROLOG__
 | 
					
						
							|  |  |  | static void init_yap(void); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | initIO(void) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   const atom_t *np; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   streamAliases = newHTable(16); | 
					
						
							|  |  |  |   streamContext = newHTable(16); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PL_register_blob_type(&stream_blob); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  |   if ( False(Sinput, SIO_ISATTY) || | 
					
						
							|  |  |  |        False(Soutput, SIO_ISATTY) ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   { /* clear PLFLAG_TTY_CONTROL */ | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     PL_set_prolog_flag("tty_control", PL_BOOL, FALSE); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   ResetTty(); | 
					
						
							| 
									
										
										
										
											2011-03-24 22:23:26 +00:00
										 |  |  | #if __YAP_PROLOG__
 | 
					
						
							|  |  |  |   /* needs to be done after tty hacking */ | 
					
						
							|  |  |  |   init_yap(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Sclosehook(freeStream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Sinput->position  = &Sinput->posbuf;	/* position logging */ | 
					
						
							|  |  |  |   Soutput->position = &Sinput->posbuf; | 
					
						
							|  |  |  |   Serror->position  = &Sinput->posbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ttymode = TTY_COOKED; | 
					
						
							|  |  |  |   PushTty(Sinput, &ttytab, TTY_SAVE); | 
					
						
							|  |  |  |   LD->prompt.current = ATOM_prompt; | 
					
						
							|  |  |  |   PL_register_atom(ATOM_prompt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Suser_input  = Sinput; | 
					
						
							|  |  |  |   Suser_output = Soutput; | 
					
						
							|  |  |  |   Suser_error  = Serror; | 
					
						
							|  |  |  |   Scurin       = Sinput;		/* see/tell */ | 
					
						
							|  |  |  |   Scurout      = Soutput; | 
					
						
							|  |  |  |   Sprotocol    = NULL;			/* protocolling */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getStreamContext(Sinput);		/* add for enumeration */ | 
					
						
							|  |  |  |   getStreamContext(Soutput); | 
					
						
							|  |  |  |   getStreamContext(Serror); | 
					
						
							|  |  |  |   for( i=0, np = standardStreams; *np; np++, i++ ) | 
					
						
							|  |  |  |     addHTable(streamAliases, (void *)*np, (void *)(intptr_t)i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GD->io_initialised = TRUE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	     GET HANDLES	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline IOSTREAM * | 
					
						
							|  |  |  | getStream(IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | { if ( s && s->magic == SIO_MAGIC && Slock(s) == 0 ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( unlikely(s->magic == SIO_CMAGIC) ) | 
					
						
							|  |  |  |     { Sunlock(s); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return s; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline IOSTREAM * | 
					
						
							|  |  |  | tryGetStream(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s && s->magic == SIO_MAGIC && StryLock(s) == 0 ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( unlikely(s->magic == SIO_CMAGIC) ) | 
					
						
							|  |  |  |     { Sunlock(s); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return s; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | releaseStream(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |     Sunlock(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else /*O_PLMT*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define getStream(s)	(s)
 | 
					
						
							|  |  |  | #define tryGetStream(s) (s)
 | 
					
						
							|  |  |  | #define releaseStream(s)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /*O_PLMT*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_release_stream(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( Sferror(s) ) | 
					
						
							|  |  |  |     return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   releaseStream(s); | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      ERRORS		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | static int symbol_no_stream(atom_t symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | no_stream(term_t t, atom_t name) | 
					
						
							|  |  |  | { if ( t ) | 
					
						
							|  |  |  |     return PL_error(NULL, 0, NULL, ERR_EXISTENCE, ATOM_stream, t); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return symbol_no_stream(name); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | not_a_stream(term_t t) | 
					
						
							|  |  |  | { return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_stream_or_alias, t); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | symbol_no_stream(atom_t symbol) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   term_t t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (t = PL_new_term_ref()) ) | 
					
						
							|  |  |  |   { PL_put_atom(t, symbol); | 
					
						
							|  |  |  |     return no_stream(t, 0); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | symbol_not_a_stream(atom_t symbol) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   term_t t = PL_new_term_ref(); | 
					
						
							|  |  |  |   PL_put_atom(t, symbol); | 
					
						
							|  |  |  |   return not_a_stream(t); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	  PROLOG HANDLES	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct stream_ref | 
					
						
							|  |  |  | { IOSTREAM *read; | 
					
						
							|  |  |  |   IOSTREAM *write; | 
					
						
							|  |  |  | } stream_ref; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | write_stream_ref(IOSTREAM *s, atom_t aref, int flags) | 
					
						
							|  |  |  | { stream_ref *ref = PL_blob_data(aref, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   (void)flags; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( ref->read && ref->write ) | 
					
						
							|  |  |  |     Sfprintf(s, "<stream>(%p,%p)", ref->read, ref->write); | 
					
						
							|  |  |  |   else if ( ref->read ) | 
					
						
							|  |  |  |     Sfprintf(s, "<stream>(%p)", ref->read); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     Sfprintf(s, "<stream>(%p)", ref->write); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | acquire_stream_ref(atom_t aref) | 
					
						
							|  |  |  | { stream_ref *ref = PL_blob_data(aref, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( ref->read ) | 
					
						
							|  |  |  |     ref->read->references++; | 
					
						
							|  |  |  |   if ( ref->write ) | 
					
						
							|  |  |  |     ref->write->references++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | release_stream_ref(atom_t aref) | 
					
						
							|  |  |  | { stream_ref *ref = PL_blob_data(aref, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ref->read ) | 
					
						
							|  |  |  |   { if ( --ref->read->references == 0 && ref->read->erased ) | 
					
						
							|  |  |  |       unallocStream(ref->read); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( ref->write ) | 
					
						
							|  |  |  |   { if ( --ref->write->references == 0 && ref->write->erased ) | 
					
						
							|  |  |  |       unallocStream(ref->write); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | save_stream_ref(atom_t aref, IOSTREAM *fd) | 
					
						
							|  |  |  | { stream_ref *ref = PL_blob_data(aref, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   (void)fd; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return PL_warning("Cannot save reference to <stream>(%p,%p)", | 
					
						
							|  |  |  | 		    ref->read, ref->write); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static atom_t | 
					
						
							|  |  |  | load_stream_ref(IOSTREAM *fd) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { (void)fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_new_atom("<saved-stream-ref>"); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PL_blob_t stream_blob = | 
					
						
							|  |  |  | { PL_BLOB_MAGIC, | 
					
						
							|  |  |  |   PL_BLOB_UNIQUE, | 
					
						
							|  |  |  |   "stream", | 
					
						
							|  |  |  |   release_stream_ref, | 
					
						
							|  |  |  |   NULL, | 
					
						
							|  |  |  |   write_stream_ref, | 
					
						
							|  |  |  |   acquire_stream_ref, | 
					
						
							|  |  |  |   save_stream_ref, | 
					
						
							|  |  |  |   load_stream_ref | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SH_ERRORS   0x01		/* generate errors */
 | 
					
						
							|  |  |  | #define SH_ALIAS    0x02		/* allow alias */
 | 
					
						
							|  |  |  | #define SH_UNLOCKED 0x04		/* don't lock the stream */
 | 
					
						
							|  |  |  | #define SH_OUTPUT   0x08		/* We want an output stream */
 | 
					
						
							|  |  |  | #define SH_INPUT    0x10		/* We want an input stream */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | get_stream_handle__LD(atom_t a, IOSTREAM **sp, int flags ARG_LD) | 
					
						
							|  |  |  | { stream_ref *ref; | 
					
						
							|  |  |  |   PL_blob_t *type; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ref = PL_blob_data(a, NULL, &type); | 
					
						
							|  |  |  |   if ( type == &stream_blob ) | 
					
						
							|  |  |  |   { if ( ref->read ) | 
					
						
							|  |  |  |     { if ( ref->write && (flags&SH_OUTPUT) ) | 
					
						
							|  |  |  | 	s = ref->write; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	s = ref->read; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       s = ref->write; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( s->erased ) | 
					
						
							|  |  |  |        goto noent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( flags & SH_UNLOCKED ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { assert( s->magic == SIO_MAGIC || s->magic == SIO_CMAGIC ); | 
					
						
							|  |  |  |       *sp = s; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       return TRUE; | 
					
						
							|  |  |  |     } else if ( (s=getStream(s)) ) | 
					
						
							|  |  |  |     { *sp = s; | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return symbol_no_stream(a); | 
					
						
							|  |  |  |   } else | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Symbol symb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !(flags & SH_UNLOCKED) ) | 
					
						
							|  |  |  |       LOCK(); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     if ( (symb=lookupHTable(streamAliases, (void *)a)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { IOSTREAM *stream; | 
					
						
							|  |  |  |       uintptr_t n = (uintptr_t)symb->value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( n < 6 )			/* standard stream! */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       { stream = LD->IO.streams[n];	/* TBD: No need to lock for std-streams */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } else | 
					
						
							|  |  |  | 	stream = symb->value; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( !(flags & SH_UNLOCKED) ) | 
					
						
							|  |  |  | 	UNLOCK(); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( stream ) | 
					
						
							|  |  |  |       { if ( (flags & SH_UNLOCKED) ) | 
					
						
							|  |  |  | 	{ if ( stream->magic == SIO_MAGIC ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	  { *sp = stream; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    return TRUE; | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	} else if ( (*sp = getStream(stream)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  return TRUE; | 
					
						
							|  |  |  | 	goto noent; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( !(flags & SH_UNLOCKED) ) | 
					
						
							|  |  |  |       UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     goto noent; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( flags & SH_ERRORS ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     symbol_not_a_stream(a); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | noent: | 
					
						
							|  |  |  |   if ( flags & SH_ERRORS ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     symbol_no_stream(a); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define get_stream_handle(t, sp, flags) \
 | 
					
						
							|  |  |  | 	get_stream_handle__LD(t, sp, flags PASS_LD) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | term_stream_handle(term_t t, IOSTREAM **s, int flags ARG_LD) | 
					
						
							|  |  |  | { atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_atom(t, &a) ) | 
					
						
							|  |  |  |     return not_a_stream(t); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   return get_stream_handle(a, s, flags); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_get_stream_handle(term_t t, IOSTREAM **s) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return term_stream_handle(t, s, SH_ERRORS|SH_ALIAS PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | unify_stream_ref(term_t t, IOSTREAM *s) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   stream_ref ref; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset(&ref, 0, sizeof(ref)); | 
					
						
							|  |  |  |   if ( s->flags & SIO_INPUT ) | 
					
						
							|  |  |  |     ref.read = s; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     ref.write = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rval = PL_unify_blob(t, &ref, sizeof(ref), &stream_blob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !rval && !PL_is_variable(t) ) | 
					
						
							|  |  |  |     return PL_error(NULL, 0, "stream-argument", ERR_UNINSTANTIATION, 0, t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_unify_stream_or_alias(term_t t, IOSTREAM *s) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  |   stream_context *ctx; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (i=standardStreamIndexFromStream(s)) >= 0 && i < 3 ) | 
					
						
							|  |  |  |     return PL_unify_atom(t, standardStreams[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK(); | 
					
						
							|  |  |  |   ctx = getStreamContext(s); | 
					
						
							|  |  |  |   if ( ctx->alias_head ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     rval = PL_unify_atom(t, ctx->alias_head->name); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     rval = unify_stream_ref(t, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-22 11:33:49 -05:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_unify_stream(term_t t, IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { LOCK(); | 
					
						
							|  |  |  |   (void)getStreamContext(s);		/* get stream known to Prolog */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   return unify_stream_ref(t, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM **				/* provide access to Suser_input, */ | 
					
						
							|  |  |  | _PL_streams(void)			/* Suser_output and Suser_error */ | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   return &Suser_input; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | getInputStream(term_t t, IOSTREAM **s) | 
					
						
							|  |  |  | getOutputStream(term_t t, IOSTREAM **s) | 
					
						
							|  |  |  |     These functions are the basis used by all Prolog predicates to get | 
					
						
							|  |  |  |     a input or output stream handle.  If t = 0, current input/output is | 
					
						
							|  |  |  |     returned.  This allows us to define the standard-stream based version | 
					
						
							|  |  |  |     simply by calling the explicit stream-based version with 0 for the | 
					
						
							|  |  |  |     stream argument. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MT: The returned stream is always locked and should be returned | 
					
						
							|  |  |  |     using releaseStream() or streamStatus(). | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | typedef enum | 
					
						
							|  |  |  | { S_DONTCARE = 0, | 
					
						
							|  |  |  |   S_TEXT, | 
					
						
							|  |  |  |   S_BINARY | 
					
						
							|  |  |  | } s_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | checkStreamType(s_type text, IOSTREAM *s, atom_t *error ARG_LD) | 
					
						
							|  |  |  | { if ( text == S_DONTCARE || LD->IO.stream_type_check == ST_FALSE ) | 
					
						
							|  |  |  |     return TRUE;			/* no checking */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* ok? */ | 
					
						
							|  |  |  |   if ( text == S_TEXT && (s->flags&SIO_TEXT) ) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   if ( text == S_BINARY && !(s->flags&SIO_TEXT) ) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 					/* no */ | 
					
						
							|  |  |  |   if ( LD->IO.stream_type_check == ST_LOOSE ) | 
					
						
							|  |  |  |   { if ( text == S_TEXT ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |     if ( s->encoding == ENC_ISO_LATIN_1 || | 
					
						
							|  |  |  | 	 s->encoding == ENC_OCTET ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *error = (text == S_TEXT ? ATOM_binary_stream : ATOM_text_stream); | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | getOutputStream__LD(term_t t, s_type text, IOSTREAM **stream ARG_LD) | 
					
						
							|  |  |  | { atom_t a; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   atom_t tp; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( t == 0 ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( (s = getStream(Scurout)) ) | 
					
						
							|  |  |  |       goto ok; | 
					
						
							|  |  |  |     return no_stream(t, ATOM_current_output); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_atom(t, &a) ) | 
					
						
							|  |  |  |     return not_a_stream(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( a == ATOM_user ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( (s = getStream(Suser_output)) ) | 
					
						
							|  |  |  |       goto ok; | 
					
						
							|  |  |  |     return no_stream(t, ATOM_user); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !get_stream_handle(a, &s, SH_ERRORS|SH_ALIAS|SH_OUTPUT) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | ok: | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !(s->flags&SIO_OUTPUT) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { tp = ATOM_stream; | 
					
						
							|  |  |  |   } else if ( checkStreamType(text, s, &tp PASS_LD) ) | 
					
						
							|  |  |  |   { *stream = s; | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   releaseStream(s); | 
					
						
							|  |  |  |   if ( t == 0 ) | 
					
						
							|  |  |  |   { if ( (t = PL_new_term_ref()) ) | 
					
						
							|  |  |  |       PL_put_atom(t, ATOM_current_output); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return FALSE;				/* resource error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		  ATOM_output, tp, t); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | getTextOutputStream__LD(term_t t, IOSTREAM **stream ARG_LD) | 
					
						
							|  |  |  | { return getOutputStream(t, S_TEXT, stream); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | getBinaryOutputStream__LD(term_t t, IOSTREAM **stream ARG_LD) | 
					
						
							|  |  |  | { return getOutputStream(t, S_BINARY, stream); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | getInputStream__LD(term_t t, s_type text, IOSTREAM **stream ARG_LD) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { atom_t a; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   atom_t tp; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( t == 0 ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( (s = getStream(Scurin)) ) | 
					
						
							|  |  |  |       goto ok; | 
					
						
							|  |  |  |     return no_stream(t, ATOM_current_input); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !PL_get_atom(t, &a) ) | 
					
						
							|  |  |  |     return not_a_stream(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( a == ATOM_user ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { if ( (s = getStream(Suser_input)) ) | 
					
						
							|  |  |  |       goto ok; | 
					
						
							|  |  |  |     return no_stream(t, ATOM_user); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !get_stream_handle(a, &s, SH_ERRORS|SH_ALIAS|SH_INPUT) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | ok: | 
					
						
							|  |  |  |   if ( !(s->flags&SIO_INPUT) ) | 
					
						
							|  |  |  |   { tp = ATOM_stream; | 
					
						
							|  |  |  |   } else if ( checkStreamType(text, s, &tp PASS_LD) ) | 
					
						
							|  |  |  |   { *stream = s; | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   releaseStream(s); | 
					
						
							|  |  |  |   if ( t == 0 ) | 
					
						
							|  |  |  |   { if ( (t = PL_new_term_ref()) ) | 
					
						
							|  |  |  |       PL_put_atom(t, ATOM_current_input); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return FALSE;				/* resource error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		  ATOM_input, tp, t); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | getTextInputStream__LD(term_t t, IOSTREAM **stream ARG_LD) | 
					
						
							|  |  |  | { return getInputStream__LD(t, S_TEXT, stream PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | getBinaryInputStream__LD(term_t t, IOSTREAM **stream ARG_LD) | 
					
						
							|  |  |  | { return getInputStream__LD(t, S_BINARY, stream PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** stream_pairs(-Pair, +Read, +Write)
 | 
					
						
							|  |  |  |  * stream_pairs(+Pair, -Read, -Write) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This SWI Built-in can be used in two ways: if the second argument is an input stream | 
					
						
							|  |  |  |  *  and the third sn output stresm, Prolog createes a new _Pair_. A stream pair can be | 
					
						
							|  |  |  |  * used in any operation, with the Prolog chosing the appropriate stream to the operation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If _Pair_ is bound, the predicate can be used to access the two streams in the pair. | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("stream_pair", 3, stream_pair, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *in = NULL, *out = NULL; | 
					
						
							|  |  |  |   int rc = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_is_variable(A1) ) | 
					
						
							|  |  |  |   { stream_ref *ref; | 
					
						
							|  |  |  |     atom_t a; | 
					
						
							|  |  |  |     PL_blob_t *type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !PL_get_atom(A1, &a) || | 
					
						
							|  |  |  | 	 !(ref=PL_blob_data(a, NULL, &type)) || | 
					
						
							|  |  |  | 	 type != &stream_blob || | 
					
						
							|  |  |  | 	 !ref->read || | 
					
						
							|  |  |  | 	 !ref->write ) | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_stream_pair, A1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( PL_unify_stream_or_alias(A2, ref->read) && | 
					
						
							|  |  |  | 	     PL_unify_stream_or_alias(A3, ref->write) ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getInputStream(A2, S_DONTCARE, &in) && | 
					
						
							|  |  |  |        getOutputStream(A3, S_DONTCARE, &out) ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { stream_ref ref; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ref.read = in; | 
					
						
							|  |  |  |     ref.write = out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rc = PL_unify_blob(A1, &ref, sizeof(ref), &stream_blob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( in ) | 
					
						
							|  |  |  |     releaseStream(in); | 
					
						
							|  |  |  |   if ( out ) | 
					
						
							|  |  |  |     releaseStream(out); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | In windows GUI applications, the IO-streams  are   not  bound. We do not | 
					
						
							|  |  |  | wish to generate an error on the  stream   errors  that may be caused by | 
					
						
							|  |  |  | this. It is a bit of a hack, but   the alternative is to define a stream | 
					
						
							|  |  |  | that ignores the error. This might get hairy if the user is playing with | 
					
						
							|  |  |  | these streams too. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | #ifdef __WINDOWS__
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | isConsoleStream(IOSTREAM *s) | 
					
						
							|  |  |  | { int i = standardStreamIndexFromStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   return i >= 1 && i < 3;			/* only output streams */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define isConsoleStream(s) FALSE
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | reportStreamError(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( GD->cleaning == CLN_NORMAL && | 
					
						
							|  |  |  |        !isConsoleStream(s) && | 
					
						
							|  |  |  |        (s->flags & (SIO_FERR|SIO_WARN)) ) | 
					
						
							|  |  |  |   { GET_LD | 
					
						
							|  |  |  |     atom_t op; | 
					
						
							|  |  |  |     term_t stream = PL_new_term_ref(); | 
					
						
							|  |  |  |     char *msg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_unify_stream_or_alias(stream, s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (s->flags & SIO_FERR) ) | 
					
						
							|  |  |  |     { if ( s->exception ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |       { fid_t fid; | 
					
						
							|  |  |  | 	term_t ex; | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LD->exception.processing = TRUE;	/* allow using spare stack */ | 
					
						
							|  |  |  | 	if ( !(fid = PL_open_foreign_frame()) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 	ex = PL_new_term_ref(); | 
					
						
							|  |  |  | 	rc = PL_recorded(s->exception, ex); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	PL_erase(s->exception); | 
					
						
							|  |  |  | 	s->exception = NULL; | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 	if ( rc ) | 
					
						
							|  |  |  | 	  rc = PL_raise_exception(ex); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	PL_close_foreign_frame(fid); | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 	return rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( s->flags & SIO_INPUT ) | 
					
						
							|  |  |  |       { if ( Sfpasteof(s) ) | 
					
						
							|  |  |  | 	{ return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 			  ATOM_input, ATOM_past_end_of_stream, stream); | 
					
						
							|  |  |  | 	} else if ( (s->flags & SIO_TIMEOUT) ) | 
					
						
							|  |  |  | 	{ PL_error(NULL, 0, NULL, ERR_TIMEOUT, | 
					
						
							|  |  |  | 		   ATOM_read, stream); | 
					
						
							|  |  |  | 	  Sclearerr(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	  return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} else | 
					
						
							|  |  |  | 	  op = ATOM_read; | 
					
						
							|  |  |  |       } else | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       { if ( (s->flags & SIO_TIMEOUT) ) | 
					
						
							|  |  |  | 	{ PL_error(NULL, 0, NULL, ERR_TIMEOUT, | 
					
						
							|  |  |  | 		   ATOM_write, stream); | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 	  op = ATOM_write; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if ( s->message ) | 
					
						
							|  |  |  |       { msg = s->message; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { msg = MSG_ERRNO; | 
					
						
							|  |  |  | 	if ( s->io_errno ) | 
					
						
							|  |  |  | 	  errno = s->io_errno; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       PL_error(NULL, 0, msg, ERR_STREAM_OP, op, stream); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( (s->flags & SIO_CLEARERR) ) | 
					
						
							|  |  |  | 	Sseterr(s, SIO_FERR, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } else | 
					
						
							|  |  |  |     { printMessage(ATOM_warning, | 
					
						
							|  |  |  | 		   PL_FUNCTOR_CHARS, "io_warning", 2, | 
					
						
							|  |  |  | 		   PL_TERM, stream, | 
					
						
							|  |  |  | 		   PL_CHARS, s->message); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Sseterr(s, SIO_WARN, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | streamStatus(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( (s->flags & (SIO_FERR|SIO_WARN)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { int ret = reportStreamError(s); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   releaseStream(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	     TTY MODES		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ttybuf	ttytab;				/* saved terminal status on entry */ | 
					
						
							|  |  |  | int	ttymode;			/* Current tty mode */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct input_context * InputContext; | 
					
						
							|  |  |  | typedef struct output_context * OutputContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct input_context | 
					
						
							|  |  |  | { IOSTREAM *    stream;                 /* pushed input */ | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   atom_t	type;			/* Type of input */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t        term_file;              /* old term_position file */ | 
					
						
							|  |  |  |   int           term_line;              /* old term_position line */ | 
					
						
							|  |  |  |   InputContext  previous;               /* previous context */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct output_context | 
					
						
							|  |  |  | { IOSTREAM *    stream;                 /* pushed output */ | 
					
						
							|  |  |  |   OutputContext previous;               /* previous context */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define input_context_stack  (LD->IO.input_stack)
 | 
					
						
							|  |  |  | #define output_context_stack (LD->IO.output_stack)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static IOSTREAM *openStream(term_t file, term_t mode, term_t options); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | dieIO() | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { if ( GD->io_initialised ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { noprotocol(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     closeFiles(TRUE); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     PopTty(Sinput, &ttytab, TRUE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | closeStream() performs Prolog-level closing. Most important right now is | 
					
						
							|  |  |  | to to avoid closing the user-streams. If a stream cannot be flushed (due | 
					
						
							|  |  |  | to a write-error), an exception is  generated. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MT: We assume the stream is locked and will unlock it here. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | closeStream(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s == Sinput ) | 
					
						
							|  |  |  |   { Sclearerr(s); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } else if ( s == Soutput || s == Serror ) | 
					
						
							|  |  |  |   { if ( Sflush(s) < 0 ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( !Sferror(s) && Sflush(s) < 0 ) | 
					
						
							|  |  |  |     { streamStatus(s); | 
					
						
							|  |  |  |       Sclose(s); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( Sclose(s) < 0 )		/* will unlock as well */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | closeFiles(int all) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   TableEnum e; | 
					
						
							|  |  |  |   Symbol symb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   e = newTableEnum(streamContext); | 
					
						
							|  |  |  |   while( (symb=advanceTableEnum(e)) ) | 
					
						
							|  |  |  |   { IOSTREAM *s = symb->name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( all || !(s->flags & SIO_NOCLOSE) ) | 
					
						
							|  |  |  |     { IOSTREAM *s2 = tryGetStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( s2 ) | 
					
						
							|  |  |  |       { if ( !all ) | 
					
						
							|  |  |  | 	{ term_t t = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  PL_unify_stream_or_alias(t, s2); | 
					
						
							|  |  |  | 	  printMessage(ATOM_informational, | 
					
						
							|  |  |  | 		       PL_FUNCTOR, FUNCTOR_close_on_abort1, | 
					
						
							|  |  |  | 		         PL_TERM, t); | 
					
						
							|  |  |  | 	  PL_reset_term_refs(t); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	closeStream(s2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   freeTableEnum(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | protocol(const char *str, size_t n) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( LD && Sprotocol && (s = getStream(Sprotocol)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { while( n-- > 0 ) | 
					
						
							|  |  |  |       Sputcode(*str++&0xff, s); | 
					
						
							|  |  |  |     Sflush(s); | 
					
						
							|  |  |  |     releaseStream(s);			/* we don not check errors */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	  TEMPORARY I/O		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | int | 
					
						
							|  |  |  | push_input_context(atom_t type) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   InputContext c = allocHeapOrHalt(sizeof(struct input_context)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PL_register_atom(type); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   c->stream           = Scurin; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   c->type	      = type; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   c->term_file        = source_file_name; | 
					
						
							|  |  |  |   c->term_line        = source_line_no; | 
					
						
							|  |  |  |   c->previous         = input_context_stack; | 
					
						
							|  |  |  |   input_context_stack = c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2011-02-10 00:02:05 +00:00
										 |  |  | pop_input_context(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   InputContext c = input_context_stack; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( c ) | 
					
						
							|  |  |  |   { Scurin              = c->stream; | 
					
						
							|  |  |  |     source_file_name    = c->term_file; | 
					
						
							|  |  |  |     source_line_no      = c->term_line; | 
					
						
							|  |  |  |     input_context_stack = c->previous; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     PL_unregister_atom(c->type); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     freeHeap(c, sizeof(struct input_context)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } else | 
					
						
							|  |  |  |   { Scurin		= Sinput; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | PRED_IMPL("$push_input_context", 1, push_input_context, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   atom_t type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_atom_ex(A1, &type) ) | 
					
						
							|  |  |  |     return push_input_context(type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("$pop_input_context", 0, pop_input_context, 0) | 
					
						
							|  |  |  | { return pop_input_context(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /** '$input_context'(-List) is det.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | True if List is a  list   of  input(Type,File,Line) terms describing the | 
					
						
							|  |  |  | current input context. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("$input_context", 1, input_context, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   term_t tail   = PL_copy_term_ref(A1); | 
					
						
							|  |  |  |   term_t head   = PL_new_term_ref(); | 
					
						
							|  |  |  |   term_t stream = PL_new_term_ref(); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   InputContext c = input_context_stack; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(c=input_context_stack; c; c=c->previous) | 
					
						
							|  |  |  |   { atom_t file = c->term_file ? c->term_file : ATOM_minus; | 
					
						
							|  |  |  |     int line = c->term_file ? c->term_line : 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     PL_put_variable(stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !PL_unify_stream_or_alias(stream, c->stream) || | 
					
						
							|  |  |  | 	 !PL_unify_list(tail, head, tail) || | 
					
						
							|  |  |  | 	 !PL_unify_term(head, PL_FUNCTOR, FUNCTOR_input4, | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 			PL_ATOM, c->type, | 
					
						
							|  |  |  | 			PL_ATOM, file, | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 			PL_INT,  line, | 
					
						
							|  |  |  | 			PL_TERM, stream) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_nil(tail); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2011-02-10 00:02:05 +00:00
										 |  |  | pushOutputContext(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   OutputContext c = allocHeapOrHalt(sizeof(struct output_context)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   c->stream            = Scurout; | 
					
						
							|  |  |  |   c->previous          = output_context_stack; | 
					
						
							|  |  |  |   output_context_stack = c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2011-02-10 00:02:05 +00:00
										 |  |  | popOutputContext(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   OutputContext c = output_context_stack; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( c ) | 
					
						
							|  |  |  |   { if ( c->stream->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |       Scurout = c->stream; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { Sdprintf("Oops, current stream closed?"); | 
					
						
							|  |  |  |       Scurout = Soutput; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     output_context_stack = c->previous; | 
					
						
							|  |  |  |     freeHeap(c, sizeof(struct output_context)); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     Scurout = Soutput; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | setupOutputRedirect(term_t to, redir_context *ctx, int redir) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ctx->term = to; | 
					
						
							|  |  |  |   ctx->redirected = redir; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( to == 0 ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { if ( !(ctx->stream = getStream(Scurout)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       return no_stream(to, ATOM_current_output); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     ctx->is_stream = TRUE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } else if ( PL_get_atom(to, &a) ) | 
					
						
							|  |  |  |   { if ( a == ATOM_user ) | 
					
						
							|  |  |  |     { if ( !(ctx->stream = getStream(Suser_output)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	return no_stream(to, ATOM_user); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       ctx->is_stream = TRUE; | 
					
						
							|  |  |  |     } else if ( get_stream_handle(a, &ctx->stream, SH_OUTPUT|SH_ERRORS) ) | 
					
						
							|  |  |  |     { if ( !(ctx->stream->flags &SIO_OUTPUT) ) | 
					
						
							|  |  |  |       { releaseStream(ctx->stream); | 
					
						
							|  |  |  | 	return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 			ATOM_output, ATOM_stream, to); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       ctx->is_stream = TRUE; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } else | 
					
						
							|  |  |  |   { if ( PL_is_functor(to, FUNCTOR_codes2) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_CODE_LIST; | 
					
						
							|  |  |  |       ctx->out_arity = 2; | 
					
						
							|  |  |  |     } else if ( PL_is_functor(to, FUNCTOR_codes1) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_CODE_LIST; | 
					
						
							|  |  |  |       ctx->out_arity = 1; | 
					
						
							|  |  |  |     } else if ( PL_is_functor(to, FUNCTOR_chars2) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_CHAR_LIST; | 
					
						
							|  |  |  |       ctx->out_arity = 2; | 
					
						
							|  |  |  |     } else if ( PL_is_functor(to, FUNCTOR_chars1) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_CHAR_LIST; | 
					
						
							|  |  |  |       ctx->out_arity = 1; | 
					
						
							|  |  |  |     } else if ( PL_is_functor(to, FUNCTOR_string1) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_STRING; | 
					
						
							|  |  |  |       ctx->out_arity = 1; | 
					
						
							|  |  |  |     } else if ( PL_is_functor(to, FUNCTOR_atom1) ) | 
					
						
							|  |  |  |     { ctx->out_format = PL_ATOM; | 
					
						
							|  |  |  |       ctx->out_arity = 1; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_output, to); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     ctx->is_stream = FALSE; | 
					
						
							|  |  |  |     ctx->data = ctx->buffer; | 
					
						
							|  |  |  |     ctx->size = sizeof(ctx->buffer); | 
					
						
							|  |  |  |     ctx->stream = Sopenmem(&ctx->data, &ctx->size, "w"); | 
					
						
							|  |  |  |     ctx->stream->encoding = ENC_WCHAR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ctx->magic = REDIR_MAGIC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( redir ) | 
					
						
							|  |  |  |   { pushOutputContext(); | 
					
						
							|  |  |  |     Scurout = ctx->stream; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | closeOutputRedirect(redir_context *ctx) | 
					
						
							|  |  |  | { int rval = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->magic != REDIR_MAGIC ) | 
					
						
							|  |  |  |     return rval;			/* already done */ | 
					
						
							|  |  |  |   ctx->magic = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->redirected ) | 
					
						
							|  |  |  |     popOutputContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->is_stream ) | 
					
						
							|  |  |  |   { rval = streamStatus(ctx->stream); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { GET_LD | 
					
						
							|  |  |  |     term_t out  = PL_new_term_ref(); | 
					
						
							|  |  |  |     term_t diff, tail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( Sclose(ctx->stream) == 0 ) | 
					
						
							|  |  |  |     { _PL_get_arg(1, ctx->term, out); | 
					
						
							|  |  |  |       if ( ctx->out_arity == 2 ) | 
					
						
							|  |  |  |       { diff = PL_new_term_ref(); | 
					
						
							|  |  |  | 	_PL_get_arg(2, ctx->term, diff); | 
					
						
							|  |  |  | 	tail = PL_new_term_ref(); | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { diff = tail = 0; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       rval = PL_unify_wchars_diff(out, tail, ctx->out_format, | 
					
						
							|  |  |  | 				  ctx->size/sizeof(wchar_t), | 
					
						
							|  |  |  | 				  (wchar_t*)ctx->data); | 
					
						
							|  |  |  |       if ( rval && tail ) | 
					
						
							|  |  |  | 	rval = PL_unify(tail, diff); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       rval = FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( ctx->data != ctx->buffer ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |       Sfree(ctx->data); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | discardOutputRedirect() is called if the `implementation' failed. One of | 
					
						
							|  |  |  | the reasons for failure  can  be   that  the  implementation  detected a | 
					
						
							|  |  |  | pending I/O stream error, in which case continuation is meaningless. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | void | 
					
						
							|  |  |  | discardOutputRedirect(redir_context *ctx) | 
					
						
							|  |  |  | { if ( ctx->magic != REDIR_MAGIC ) | 
					
						
							|  |  |  |     return;				/* already done */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ctx->magic = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->redirected ) | 
					
						
							|  |  |  |     popOutputContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ctx->is_stream ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { streamStatus(ctx->stream); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } else | 
					
						
							|  |  |  |   { closeStream(ctx->stream); | 
					
						
							|  |  |  |     if ( ctx->data != ctx->buffer ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |       Sfree(ctx->data); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  with_output_to(+ _Ouput_,: _Goal_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This SWI-Prolog predicate runs  _Goal_ as once/1, while characters written to the current | 
					
						
							|  |  |  | output are sent to  _Output_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This predicate supports creating | 
					
						
							|  |  |  | difference-lists from character data efficiently. The example below | 
					
						
							|  |  |  | defines the DCG rule `term/3` to insert a term in the output: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ~~~~~ | 
					
						
							|  |  |  |  term(Term, In, Tail) :- | 
					
						
							|  |  |  |         with_output_to(codes(In, Tail), write(Term)). | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | ?- phrase(term(hello), X). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | X = [104, 101, 108, 108, 111] | 
					
						
							|  |  |  | ~~~~~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + A Stream handle or alias | 
					
						
							|  |  |  | Temporary switch current output to the given stream. Redirection using with_output_to/2 guarantees the original output is restored, also if Goal fails or raises an exception. See also call_cleanup/2. | 
					
						
							|  |  |  | + atom(- _Atom_) | 
					
						
							|  |  |  | Create an atom from the emitted characters. Please note that there is a cost in creating atoms. | 
					
						
							|  |  |  | + string(- _String_) | 
					
						
							|  |  |  | Create a string-object. | 
					
						
							|  |  |  | + codes(- _Codes_) | 
					
						
							|  |  |  | Create a list of character codes from the emitted characters, similar to atom_codes/2. | 
					
						
							|  |  |  | + codes(- _Codes_, - _Tail_) | 
					
						
							|  |  |  | Create a list of character codes as a difference-list. | 
					
						
							|  |  |  | + chars(- _Chars_) | 
					
						
							|  |  |  | Create a list of one-character-atoms codes from the emitted characters, similar to atom_chars/2. | 
					
						
							|  |  |  | + chars(- _Chars_, - _Tail_) | 
					
						
							|  |  |  | Create a list of one-character-atoms as a difference-list. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("with_output_to", 2, with_output_to, PL_FA_TRANSPARENT) | 
					
						
							|  |  |  | { redir_context outctx; | 
					
						
							| 
									
										
										
										
											2014-06-14 10:27:39 +01:00
										 |  |  |   outctx.magic = 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( setupOutputRedirect(A1, &outctx, TRUE) ) | 
					
						
							|  |  |  |   { term_t ex = 0; | 
					
						
							|  |  |  |     int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (rval = callProlog(NULL, A2, PL_Q_CATCH_EXCEPTION, &ex)) ) | 
					
						
							|  |  |  |       return closeOutputRedirect(&outctx); | 
					
						
							|  |  |  |     discardOutputRedirect(&outctx); | 
					
						
							|  |  |  |     if ( ex ) | 
					
						
							|  |  |  |       return PL_raise_exception(ex); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_write_prompt(int dowrite) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							| 
									
										
										
										
											2014-02-20 10:38:18 +00:00
										 |  |  | #if __YAP_PROLOG__
 | 
					
						
							|  |  |  |   IOSTREAM *s = getStream(Suser_error); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s = getStream(Suser_output); | 
					
						
							| 
									
										
										
										
											2014-02-20 10:38:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( s ) | 
					
						
							|  |  |  |   { if ( dowrite ) | 
					
						
							|  |  |  |     { atom_t a = PrologPrompt(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( a ) | 
					
						
							|  |  |  | 	writeAtomToStream(s, a); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Sflush(s); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LD->prompt.next = FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Get a single character from Sinput  without   waiting  for a return. The | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | character should not be echoed.  If   PLFLAG_TTY_CONTROL  is false this | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | function will read the first character and  then skip all character upto | 
					
						
							|  |  |  | and including the newline. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sgetcode_intr(IOSTREAM *s, int signals) | 
					
						
							|  |  |  | { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   int newline = s->newline; | 
					
						
							|  |  |  |   s->newline = SIO_NL_POSIX;		/* avoid blocking \r */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   do | 
					
						
							|  |  |  |   { Sclearerr(s); | 
					
						
							|  |  |  |     c = Sgetcode(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   } while ( c == -1 && | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    errno == EINTR && | 
					
						
							|  |  |  | 	    (!signals || PL_handle_signals() >= 0) | 
					
						
							|  |  |  | 	  ); | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   s->newline = newline; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | getSingleChar(IOSTREAM *stream, int signals) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   int c; | 
					
						
							|  |  |  |   ttybuf buf; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   suspendTrace(TRUE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Slock(stream); | 
					
						
							|  |  |  |   Sflush(stream); | 
					
						
							|  |  |  |   PushTty(stream, &buf, TTY_RAW);	/* just donot prompt */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( !truePrologFlag(PLFLAG_TTY_CONTROL) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int c2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c2 = Sgetcode_intr(stream, signals); | 
					
						
							|  |  |  |     while( c2 == ' ' || c2 == '\t' )	/* skip blanks */ | 
					
						
							|  |  |  |       c2 = Sgetcode_intr(stream, signals); | 
					
						
							|  |  |  |     c = c2; | 
					
						
							|  |  |  |     while( c2 != EOF && c2 != '\n' )	/* read upto newline */ | 
					
						
							|  |  |  |       c2 = Sgetcode_intr(stream, signals); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( stream->position ) | 
					
						
							|  |  |  |     { IOPOS oldpos = *stream->position; | 
					
						
							|  |  |  |       c = Sgetcode_intr(stream, signals); | 
					
						
							|  |  |  |       *stream->position = oldpos; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       c = Sgetcode_intr(stream, signals); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( c == 4 || c == 26 )		/* should ask the terminal! */ | 
					
						
							|  |  |  |     c = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PopTty(stream, &buf, TRUE); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   suspendTrace(FALSE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Sunlock(stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | readLine() reads a line from the terminal.  It is used only by the tracer. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef DEL
 | 
					
						
							|  |  |  | #define DEL 127
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | readLine(IOSTREAM *in, IOSTREAM *out, char *buffer) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   int c; | 
					
						
							|  |  |  |   char *buf = &buffer[strlen(buffer)]; | 
					
						
							|  |  |  |   ttybuf tbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Slock(in); | 
					
						
							|  |  |  |   Slock(out); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PushTty(in, &tbuf, TTY_RAW);		/* just donot prompt */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { Sflush(out); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     switch( (c=Sgetcode_intr(in, FALSE)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { case '\n': | 
					
						
							|  |  |  |       case '\r': | 
					
						
							|  |  |  |       case EOF: | 
					
						
							|  |  |  |         *buf++ = EOS; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |         PopTty(in, &tbuf, TRUE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	Sunlock(in); | 
					
						
							|  |  |  | 	Sunlock(out); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return c == EOF ? FALSE : TRUE; | 
					
						
							|  |  |  |       case '\b': | 
					
						
							|  |  |  |       case DEL: | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	if ( truePrologFlag(PLFLAG_TTY_CONTROL) && buf > buffer ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	{ Sfputs("\b \b", out); | 
					
						
							|  |  |  | 	  buf--; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	  continue; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-13 12:54:06 +00:00
										 |  |  |         /*FALLTHROUGH*/ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       default: | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	if ( truePrologFlag(PLFLAG_TTY_CONTROL) ) | 
					
						
							|  |  |  | 	  Sputcode(c, out); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	*buf++ = c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-13 12:54:06 +00:00
										 |  |  |   return FALSE; /* make eclipse happy */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | IOSTREAM * | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_current_input() | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   return getStream(Scurin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | IOSTREAM * | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PL_current_output() | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   return getStream(Scurout); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | openProtocol(term_t f, int appnd) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   term_t mode = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   noprotocol(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PL_put_atom(mode, appnd ? ATOM_append : ATOM_write); | 
					
						
							|  |  |  |   if ( (s = openStream(f, mode, 0)) ) | 
					
						
							|  |  |  |   { s->flags |= SIO_NOCLOSE;		/* do not close on abort */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Sprotocol = s; | 
					
						
							|  |  |  |     Suser_input->tee = s; | 
					
						
							|  |  |  |     Suser_output->tee = s; | 
					
						
							|  |  |  |     Suser_error->tee = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | noprotocol(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( Sprotocol && (s = getStream(Sprotocol)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { TableEnum e; | 
					
						
							|  |  |  |     Symbol symb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     e = newTableEnum(streamContext); | 
					
						
							|  |  |  |     while( (symb=advanceTableEnum(e)) ) | 
					
						
							|  |  |  |     { IOSTREAM *p = symb->name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( p->tee == s ) | 
					
						
							|  |  |  | 	p->tee = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     freeTableEnum(e); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     closeStream(s); | 
					
						
							|  |  |  |     Sprotocol = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred noprotocol
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | Stop protocolling user interaction. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("noprotocol", 0, noprotocol, 0) | 
					
						
							|  |  |  | { return noprotocol(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | //! @}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //  @{
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	 STREAM ATTRIBUTES	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | setCloseOnExec(IOSTREAM *s, int val) | 
					
						
							|  |  |  | { int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (fd = Sfileno(s)) < 0) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(F_SETFD) && defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  |   { int fd_flags = fcntl(fd, F_GETFD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( fd_flags == -1 ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( val ) | 
					
						
							|  |  |  |       fd_flags |= FD_CLOEXEC; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       fd_flags &= ~FD_CLOEXEC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( fcntl(fd, F_SETFD, fd_flags) == -1 ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #elif defined __WINDOWS__
 | 
					
						
							|  |  |  |   { if ( !SetHandleInformation((HANDLE)_get_osfhandle(fd), | 
					
						
							|  |  |  | 			       HANDLE_FLAG_INHERIT, !val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | /* returns TRUE: ok, FALSE: error, -1: not available
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | set_stream(IOSTREAM *s, term_t stream, atom_t aname, term_t a ARG_LD) | 
					
						
							|  |  |  | { if ( aname == ATOM_alias )	/* alias(name) */ | 
					
						
							|  |  |  |   { atom_t alias; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &alias) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( (i=standardStreamIndexFromName(alias)) >= 0 ) | 
					
						
							|  |  |  |     { LD->IO.streams[i] = s; | 
					
						
							|  |  |  |       if ( i == 0 ) | 
					
						
							|  |  |  | 	LD->prompt.next = TRUE;	/* changed standard input: prompt! */ | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     LOCK(); | 
					
						
							|  |  |  |     aliasStream(s, alias); | 
					
						
							|  |  |  |     UNLOCK(); | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_buffer ) /* buffer(Buffering) */ | 
					
						
							|  |  |  |   { atom_t b; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #define SIO_ABUF (SIO_FBUF|SIO_LBUF|SIO_NBUF)
 | 
					
						
							|  |  |  |     if ( !PL_get_atom_ex(a, &b) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( b == ATOM_full ) | 
					
						
							|  |  |  |     { s->flags &= ~SIO_ABUF; | 
					
						
							|  |  |  |       s->flags |= SIO_FBUF; | 
					
						
							|  |  |  |     } else if ( b == ATOM_line ) | 
					
						
							|  |  |  |     { s->flags &= ~SIO_ABUF; | 
					
						
							|  |  |  |       s->flags |= SIO_LBUF; | 
					
						
							|  |  |  |     } else if ( b == ATOM_false ) | 
					
						
							|  |  |  |     { Sflush(s); | 
					
						
							|  |  |  |       s->flags &= ~SIO_ABUF; | 
					
						
							|  |  |  |       s->flags |= SIO_NBUF; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { return PL_error("set_stream", 2, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 		      ATOM_buffer, a); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_buffer_size ) | 
					
						
							|  |  |  |   { int size; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_integer_ex(a, &size) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( size < 1 ) | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_not_less_than_one, a); | 
					
						
							|  |  |  |     Ssetbuffer(s, NULL, size); | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_eof_action ) /* eof_action(Action) */ | 
					
						
							|  |  |  |   { atom_t action; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &action) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( action == ATOM_eof_code ) | 
					
						
							|  |  |  |     { s->flags &= ~(SIO_NOFEOF|SIO_FEOF2ERR); | 
					
						
							|  |  |  |     } else if ( action == ATOM_reset ) | 
					
						
							|  |  |  |     { s->flags &= ~SIO_FEOF2ERR; | 
					
						
							|  |  |  |       s->flags |= SIO_NOFEOF; | 
					
						
							|  |  |  |     } else if ( action == ATOM_error ) | 
					
						
							|  |  |  |     { s->flags &= ~SIO_NOFEOF; | 
					
						
							|  |  |  |       s->flags |= SIO_FEOF2ERR; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { PL_error("set_stream", 2, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 	       ATOM_eof_action, a); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_type ) /* type(Type) */ | 
					
						
							|  |  |  |   { atom_t type; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &type) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( type == ATOM_text ) | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  |     { if ( False(s, SIO_TEXT) && Ssetenc(s, LD->encoding, NULL) != 0 ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 			ATOM_encoding, ATOM_stream, stream); | 
					
						
							|  |  |  |       s->flags |= SIO_TEXT; | 
					
						
							|  |  |  |     } else if ( type == ATOM_binary ) | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  |     { if ( True(s, SIO_TEXT) && Ssetenc(s, ENC_OCTET, NULL) != 0 ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 			ATOM_encoding, ATOM_stream, stream); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       s->flags &= ~SIO_TEXT; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { return PL_error("set_stream", 2, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 		      ATOM_type, a); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_close_on_abort ) /* close_on_abort(Bool) */ | 
					
						
							|  |  |  |   { int close; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_bool_ex(a, &close) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( close ) | 
					
						
							|  |  |  |       s->flags &= ~SIO_NOCLOSE; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       s->flags |= SIO_NOCLOSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_record_position ) | 
					
						
							|  |  |  |   { int rec; | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_bool_ex(a, &rec) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( rec ) | 
					
						
							|  |  |  |       s->position = &s->posbuf; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       s->position = NULL; | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_line_position ) | 
					
						
							|  |  |  |   { int lpos; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_integer_ex(a, &lpos) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( s->position ) | 
					
						
							|  |  |  |       s->position->linepos = lpos; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		      ATOM_line_position, ATOM_stream, stream); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_file_name ) /* file_name(Atom) */ | 
					
						
							|  |  |  |   {	atom_t fn; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &fn) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     setFileNameStream(s, fn); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_timeout ) | 
					
						
							|  |  |  |   { double f; | 
					
						
							|  |  |  |     atom_t v; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( PL_get_atom(a, &v) && v == ATOM_infinite ) | 
					
						
							|  |  |  |     { s->timeout = -1; | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( !PL_get_float_ex(a, &f) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     s->timeout = (int)(f*1000.0); | 
					
						
							|  |  |  |     if ( s->timeout < 0 ) | 
					
						
							|  |  |  |       s->timeout = 0; | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_tty )	/* tty(bool) */ | 
					
						
							|  |  |  |   {	int val; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_bool_ex(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( val ) | 
					
						
							|  |  |  |       set(s, SIO_ISATTY); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       clear(s, SIO_ISATTY); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_encoding )	/* encoding(atom) */ | 
					
						
							|  |  |  |   {	atom_t val; | 
					
						
							|  |  |  |     IOENC enc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( (enc = atom_to_encoding(val)) == ENC_UNKNOWN ) | 
					
						
							|  |  |  |     { bad_encoding(NULL, val); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( Ssetenc(s, enc, NULL) == 0 ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		    ATOM_encoding, ATOM_stream, stream); | 
					
						
							|  |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   } else if ( aname == ATOM_locale )	/* locale(Locale) */ | 
					
						
							|  |  |  |   {	PL_locale *val; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !getLocaleEx(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( Ssetlocale(s, val, NULL) == 0 ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		    ATOM_locale, ATOM_stream, stream); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   } else if ( aname == ATOM_representation_errors ) | 
					
						
							|  |  |  |   { atom_t val; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     clear(s, SIO_REPXML|SIO_REPPL); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 12:54:06 +00:00
										 |  |  |     if ( val == ATOM_error ) { | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       ; | 
					
						
							| 
									
										
										
										
											2014-03-13 12:54:06 +00:00
										 |  |  |     } else if ( val == ATOM_xml ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       set(s, SIO_REPXML); | 
					
						
							|  |  |  |     else if ( val == ATOM_prolog ) | 
					
						
							|  |  |  |       set(s, SIO_REPPL); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 		      ATOM_representation_errors, a); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_newline ) | 
					
						
							|  |  |  |   { atom_t val; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_atom_ex(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     if ( val == ATOM_posix ) | 
					
						
							|  |  |  |       s->newline = SIO_NL_POSIX; | 
					
						
							|  |  |  |     else if ( val == ATOM_dos ) | 
					
						
							|  |  |  |       s->newline = SIO_NL_DOS; | 
					
						
							|  |  |  |     else if ( val == ATOM_detect ) | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  |     { if ( False(s, SIO_INPUT) ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	return PL_error(NULL, 0, "detect only allowed for input streams", | 
					
						
							|  |  |  | 			ERR_DOMAIN, ATOM_newline, a); | 
					
						
							|  |  |  |       s->newline = SIO_NL_DETECT; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_newline, a); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( aname == ATOM_close_on_exec ) /* close_on_exec(bool) */ | 
					
						
							|  |  |  |   { int val; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     if ( !PL_get_bool_ex(a, &val) ) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return setCloseOnExec(s, val); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { assert(0); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | typedef struct set_stream_info | 
					
						
							|  |  |  | { atom_t name; | 
					
						
							|  |  |  |   int    flags; | 
					
						
							|  |  |  | } set_stream_info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SS_READ		0x01
 | 
					
						
							|  |  |  | #define SS_WRITE	0x02
 | 
					
						
							|  |  |  | #define SS_BOTH		(SS_READ|SS_WRITE)
 | 
					
						
							|  |  |  | #define SS_NOPAIR	(0x4|SS_BOTH)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SS_INFO(name, flags) { name, flags }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const set_stream_info ss_info[] = | 
					
						
							|  |  |  | { SS_INFO(ATOM_alias,		      SS_NOPAIR), | 
					
						
							|  |  |  |   SS_INFO(ATOM_buffer,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_buffer_size,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_eof_action,	      SS_READ), | 
					
						
							|  |  |  |   SS_INFO(ATOM_type,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_close_on_abort,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_record_position,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_line_position,	      SS_NOPAIR), | 
					
						
							|  |  |  |   SS_INFO(ATOM_file_name,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_timeout,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_tty,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_encoding,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_locale,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_representation_errors, SS_WRITE), | 
					
						
							|  |  |  |   SS_INFO(ATOM_newline,		      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO(ATOM_close_on_exec,	      SS_BOTH), | 
					
						
							|  |  |  |   SS_INFO((atom_t)0,		      0) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  set_stream(+ _S_, + _Prop_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Set a property _Prop_ for a stream  _S_. | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_stream", 2, set_stream, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   atom_t sblob, aname; | 
					
						
							|  |  |  |   stream_ref *ref; | 
					
						
							|  |  |  |   PL_blob_t *type; | 
					
						
							|  |  |  |   int rc, arity; | 
					
						
							|  |  |  |   const set_stream_info *info; | 
					
						
							|  |  |  |   term_t aval = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   term_t stream = A1; | 
					
						
							|  |  |  |   term_t attr = A2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_name_arity(attr, &aname, &arity) && arity == 1 ) | 
					
						
							|  |  |  |   { for(info = ss_info; info->name; info++) | 
					
						
							|  |  |  |     { if ( info->name == aname ) | 
					
						
							|  |  |  | 	goto found; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PL_domain_error("stream_attribute", attr); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     return PL_type_error("stream_attribute", attr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | found: | 
					
						
							|  |  |  |   _PL_get_arg(1, attr, aval); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_atom(stream, &sblob) ) | 
					
						
							|  |  |  |     return not_a_stream(stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ref = PL_blob_data(sblob, NULL, &type); | 
					
						
							|  |  |  |   if ( type == &stream_blob )		/* got a stream handle */ | 
					
						
							|  |  |  |   { if ( ref->read && ref->write &&	/* stream pair */ | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  | 	 (info->flags & SS_NOPAIR) ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       return PL_error("set_stream", 2, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 		      aname, ATOM_stream_pair, stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rc = TRUE; | 
					
						
							|  |  |  |     if ( ref->read && (info->flags&SS_READ)) | 
					
						
							|  |  |  |     { if ( !(s = getStream(ref->read)) ) | 
					
						
							|  |  |  |         return symbol_no_stream(sblob); | 
					
						
							|  |  |  |       rc = set_stream(s, stream, aname, aval PASS_LD); | 
					
						
							|  |  |  |       releaseStream(ref->read); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( rc && ref->write && (info->flags&SS_WRITE) ) | 
					
						
							|  |  |  |     { if ( !(s = getStream(ref->write)) ) | 
					
						
							|  |  |  |         return symbol_no_stream(sblob); | 
					
						
							|  |  |  |       rc = set_stream(s, stream, aname, aval PASS_LD); | 
					
						
							|  |  |  |       releaseStream(ref->write); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else if ( PL_get_stream_handle(stream, &s) ) | 
					
						
							|  |  |  |   { rc = set_stream(s, stream, aname, aval PASS_LD); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     rc = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( rc < 0 )				/* not on this OS */ | 
					
						
							|  |  |  |     return PL_domain_error("stream_attribute", attr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | #ifdef _MSC_VER					/* defined in pl-nt.c */
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | extern int ftruncate(int fileno, int64_t length); | 
					
						
							|  |  |  | #define HAVE_FTRUNCATE
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  set_end_of_stream(+ _S_ ) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Set stream position  to be the end of stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_end_of_stream", 1, set_end_of_stream, 0) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  |   int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (rc=PL_get_stream_handle(A1, &s)) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  | #ifdef HAVE_FTRUNCATE
 | 
					
						
							|  |  |  |     int fileno = Sfileno(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( fileno >= 0 ) | 
					
						
							|  |  |  |     { if ( ftruncate(fileno, Stell64(s)) != 0 ) | 
					
						
							|  |  |  | 	rc = PL_error(NULL, 0, MSG_ERRNO, ERR_FILE_OPERATION, | 
					
						
							|  |  |  | 		      ATOM_set_end_of_stream, ATOM_stream, | 
					
						
							|  |  |  | 		      A1); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { rc = PL_error(NULL, 0, "not a file", ERR_PERMISSION, | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 		    ATOM_set_end_of_stream, ATOM_stream, A1); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     rc = notImplemented("set_end_of_stream", 1); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/********************************
 | 
					
						
							|  |  |  | 		*          STRING I/O           * | 
					
						
							|  |  |  | 		*********************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern IOFUNCTIONS Smemfunctions; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | tellString(char **s, size_t *size, IOENC enc) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *stream; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   stream = Sopenmem(s, size, "w"); | 
					
						
							|  |  |  |   stream->encoding = enc; | 
					
						
							|  |  |  |   pushOutputContext(); | 
					
						
							|  |  |  |   Scurout = stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  | bool | 
					
						
							|  |  |  | toldString(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s = getStream(Scurout); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !s ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( s->functions == &Smemfunctions ) | 
					
						
							|  |  |  |   { closeStream(s); | 
					
						
							|  |  |  |     popOutputContext(); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/********************************
 | 
					
						
							|  |  |  | 		*       WAITING FOR INPUT	* | 
					
						
							|  |  |  | 		********************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef HAVE_SELECT
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  wait_for_input(+ _Streams_, -_Available_, - _Timeout_) is iso
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Implement the select operation over a set of stream _Streams, with | 
					
						
							|  |  |  |  *  _Available_ unified with all ready streams. The operation can last at most | 
					
						
							|  |  |  |  *  _Timeout_ seconds. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("wait_for_input", 3, wait_for_input, 0) | 
					
						
							|  |  |  | { return notImplemented("wait_for_input", 3); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Windows<->Unix note. This function uses the   Windows socket API for its | 
					
						
							|  |  |  | implementation and defines the Unix API  in   terms  of the Windows API. | 
					
						
							|  |  |  | This approach allows full support  of   the  restrictions of the Windows | 
					
						
							|  |  |  | implementation. Because the Unix emulation is   more generic, this still | 
					
						
							|  |  |  | supports  the  generic  facilities  of  Unix  select()  that  make  this | 
					
						
							|  |  |  | predicate work on pipes, serial devices, etc. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __WINDOWS__
 | 
					
						
							|  |  |  | typedef int SOCKET; | 
					
						
							|  |  |  | #define INVALID_SOCKET -1
 | 
					
						
							|  |  |  | #define Swinsock(s) Sfileno(s)
 | 
					
						
							|  |  |  | #define NFDS(max) (max+1)			/* see also S__wait() */
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define NFDS(n) 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | typedef struct fdentry | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { SOCKET fd; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   term_t stream; | 
					
						
							|  |  |  |   struct fdentry *next; | 
					
						
							|  |  |  | } fdentry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("wait_for_input", 3, wait_for_input, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   fd_set fds; | 
					
						
							|  |  |  |   struct timeval t, *to; | 
					
						
							|  |  |  |   double time; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   int rc; | 
					
						
							|  |  |  | #ifndef __WINDOWS__
 | 
					
						
							|  |  |  |   SOCKET max = 0, min = INT_MAX; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   fdentry *map     = NULL; | 
					
						
							|  |  |  |   term_t head      = PL_new_term_ref(); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t streams   = PL_copy_term_ref(A1); | 
					
						
							|  |  |  |   term_t available = PL_copy_term_ref(A2); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   term_t ahead     = PL_new_term_ref(); | 
					
						
							|  |  |  |   int from_buffer  = 0; | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t timeout = A3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   FD_ZERO(&fds); | 
					
						
							|  |  |  |   while( PL_get_list(streams, head, streams) ) | 
					
						
							|  |  |  |   { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     SOCKET fd; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     fdentry *e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !PL_get_stream_handle(head, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     if ( (fd=Swinsock(s)) < 0 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { releaseStream(s); | 
					
						
							|  |  |  |       return PL_error("wait_for_input", 3, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 		      PL_new_atom("file_stream"), head); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  | 					/* check for input in buffer */ | 
					
						
							|  |  |  |     if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |     { if ( !PL_unify_list(available, ahead, available) || | 
					
						
							|  |  |  | 	   !PL_unify(ahead, head) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       from_buffer++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     e         = alloca(sizeof(*e)); | 
					
						
							|  |  |  |     e->fd     = fd; | 
					
						
							|  |  |  |     e->stream = PL_copy_term_ref(head); | 
					
						
							|  |  |  |     e->next   = map; | 
					
						
							|  |  |  |     map       = e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FD_SET(fd, &fds); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | #ifndef __WINDOWS__
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( fd > max ) | 
					
						
							|  |  |  |       max = fd; | 
					
						
							|  |  |  |     if( fd < min ) | 
					
						
							|  |  |  |       min = fd; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   if ( !PL_get_nil(streams) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return PL_error("wait_for_input", 3, NULL, ERR_TYPE, ATOM_list, A1); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( from_buffer > 0 ) | 
					
						
							|  |  |  |     return PL_unify_nil(available); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_atom(timeout, &a) && a == ATOM_infinite ) | 
					
						
							|  |  |  |   { to = NULL; | 
					
						
							|  |  |  |   } else if ( PL_is_integer(timeout) ) | 
					
						
							|  |  |  |   { long v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_get_long(timeout, &v); | 
					
						
							|  |  |  |     if ( v > 0L ) | 
					
						
							|  |  |  |     { t.tv_sec = v; | 
					
						
							|  |  |  |       t.tv_usec = 0; | 
					
						
							|  |  |  |       to = &t; | 
					
						
							|  |  |  |     } else if ( v == 0 ) | 
					
						
							|  |  |  |     { to = NULL; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { t.tv_sec  = 0; | 
					
						
							|  |  |  |       t.tv_usec = 0; | 
					
						
							|  |  |  |       to = &t; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( !PL_get_float(timeout, &time) ) | 
					
						
							|  |  |  |       return PL_error("wait_for_input", 3, NULL, | 
					
						
							|  |  |  | 		      ERR_TYPE, ATOM_float, timeout); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( time >= 0.0 ) | 
					
						
							|  |  |  |     { t.tv_sec  = (int)time; | 
					
						
							|  |  |  |       t.tv_usec = ((int)(time * 1000000) % 1000000); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { t.tv_sec  = 0; | 
					
						
							|  |  |  |       t.tv_usec = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     to = &t; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   while( (rc=select(NFDS(max), &fds, NULL, NULL, to)) == -1 && | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	 errno == EINTR ) | 
					
						
							|  |  |  |   { fdentry *e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( PL_handle_signals() < 0 ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE;				/* exception */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     FD_ZERO(&fds);			/* EINTR may leave fds undefined */ | 
					
						
							|  |  |  |     for(e=map; e; e=e->next)		/* so we rebuild it to be safe */ | 
					
						
							|  |  |  |       FD_SET(e->fd, &fds); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   switch(rc) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { case -1: | 
					
						
							|  |  |  |       return PL_error("wait_for_input", 3, MSG_ERRNO, ERR_FILE_OPERATION, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 		      ATOM_select, ATOM_stream, A1); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 0: /* Timeout */ | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: /* Something happend -> check fds */ | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { fdentry *mp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(mp=map; mp; mp=mp->next) | 
					
						
							|  |  |  |       { if ( FD_ISSET(mp->fd, &fds) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	{ if ( !PL_unify_list(available, ahead, available) || | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	       !PL_unify(ahead, mp->stream) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	    return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_nil(available); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* HAVE_SELECT */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/********************************
 | 
					
						
							|  |  |  | 		*      PROLOG CONNECTION        * | 
					
						
							|  |  |  | 		*********************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_PENDING SIO_BUFSIZE		/* 4096 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | re_buffer(IOSTREAM *s, const char *from, size_t len) | 
					
						
							|  |  |  | { if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |   { size_t size = s->limitp - s->bufp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memmove(s->buffer, s->bufp, size); | 
					
						
							|  |  |  |     s->bufp = s->buffer; | 
					
						
							|  |  |  |     s->limitp = &s->bufp[size]; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { s->bufp = s->limitp = s->buffer; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memcpy(s->bufp, from, len); | 
					
						
							|  |  |  |   s->bufp += len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef HAVE_MBSNRTOWCS
 | 
					
						
							|  |  |  | static size_t | 
					
						
							|  |  |  | mbsnrtowcs(wchar_t *dest, const char **src, | 
					
						
							|  |  |  | 	   size_t nms, size_t len, mbstate_t *ps) | 
					
						
							|  |  |  | { wchar_t c; | 
					
						
							|  |  |  |   const char *us = *src; | 
					
						
							|  |  |  |   const char *es = us+nms; | 
					
						
							|  |  |  |   size_t count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert(dest == NULL);			/* incomplete implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while(us<es) | 
					
						
							|  |  |  |   { size_t skip = mbrtowc(&c, us, es-us, ps); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( skip == (size_t)-1 )		/* error */ | 
					
						
							|  |  |  |     { DEBUG(1, Sdprintf("mbsnrtowcs(): bad multibyte seq\n")); | 
					
						
							|  |  |  |       return skip; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( skip == (size_t)-2 )		/* incomplete */ | 
					
						
							|  |  |  |     { *src = us; | 
					
						
							|  |  |  |       return count; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     count++; | 
					
						
							|  |  |  |     us += skip; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *src = us; | 
					
						
							|  |  |  |   return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #if defined(HAVE_DECL_MBSNRTOWCS) && !HAVE_DECL_MBSNRTOWCS
 | 
					
						
							|  |  |  | size_t mbsnrtowcs(wchar_t *dest, const char **src, | 
					
						
							|  |  |  | 		  size_t nms, size_t len, mbstate_t *ps); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif /*HAVE_MBSNRTOWCS*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | skip_cr(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->flags&SIO_TEXT ) | 
					
						
							|  |  |  |   { switch(s->newline) | 
					
						
							|  |  |  |     { case SIO_NL_DETECT: | 
					
						
							|  |  |  | 	s->newline = SIO_NL_DOS; | 
					
						
							|  |  |  |         /*FALLTHROUGH*/ | 
					
						
							|  |  |  |       case SIO_NL_DOS: | 
					
						
							|  |  |  | 	return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred read_pending_input( _Stream_ , _Codes_, _End_ )
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Reads all characters or bytes currently available from _Stream_ to the difference | 
					
						
							|  |  |  |  * list _Codes_ - _End_. This SWI predicate allows cleaning up input from unbuffered | 
					
						
							|  |  |  |  * streams. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("read_pending_input", 3, read_pending_input, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getInputStream(A1, S_DONTCARE, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { char buf[MAX_PENDING]; | 
					
						
							|  |  |  |     ssize_t n; | 
					
						
							|  |  |  |     int64_t off0 = Stell64(s); | 
					
						
							|  |  |  |     IOPOS pos0; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     list_ctx ctx; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( Sferror(s) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n = Sread_pending(s, buf, sizeof(buf), 0); | 
					
						
							|  |  |  |     if ( n < 0 )			/* should not happen */ | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  |     if ( n == 0 )			/* end-of-file */ | 
					
						
							|  |  |  |     { S__fcheckpasteeof(s, -1); | 
					
						
							|  |  |  |       return PL_unify(A2, A3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( s->position ) | 
					
						
							|  |  |  |     { pos0 = *s->position; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { memset(&pos0, 0, sizeof(pos0));	/* make compiler happy */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch(s->encoding) | 
					
						
							|  |  |  |     { case ENC_OCTET: | 
					
						
							|  |  |  |       case ENC_ISO_LATIN_1: | 
					
						
							|  |  |  |       case ENC_ASCII: | 
					
						
							|  |  |  |       { ssize_t i; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ( !allocList(n, &ctx) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(i=0; i<n; i++) | 
					
						
							|  |  |  | 	{ int c = buf[i]&0xff; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  if ( c == '\r' && skip_cr(s) ) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( s->position ) | 
					
						
							|  |  |  | 	    S__fupdatefilepos_getc(s, c); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  addSmallIntList(&ctx, c); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno = pos0.byteno+n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       case ENC_ANSI: | 
					
						
							|  |  |  |       { size_t count, i; | 
					
						
							|  |  |  | 	mbstate_t s0; | 
					
						
							|  |  |  | 	const char *us = buf; | 
					
						
							|  |  |  | 	const char *es = buf+n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( !s->mbstate ) | 
					
						
							|  |  |  | 	{ if ( !(s->mbstate = malloc(sizeof(*s->mbstate))) ) | 
					
						
							|  |  |  | 	  { PL_error(NULL, 0, NULL, ERR_NOMEM); | 
					
						
							|  |  |  | 	    goto failure; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  memset(s->mbstate, 0, sizeof(*s->mbstate)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s0 = *s->mbstate; | 
					
						
							|  |  |  | 	count = mbsnrtowcs(NULL, &us, n, 0, &s0); | 
					
						
							|  |  |  | 	if ( count == (size_t)-1 ) | 
					
						
							|  |  |  | 	{ Sseterr(s, SIO_WARN, "Illegal multibyte Sequence"); | 
					
						
							|  |  |  | 	  goto failure; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	DEBUG(2, Sdprintf("Got %ld codes from %d bytes; incomplete: %ld\n", | 
					
						
							|  |  |  | 			  count, n, es-us)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	if ( !allocList(count, &ctx) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(us=buf,i=0; i<count; i++) | 
					
						
							|  |  |  | 	{ wchar_t c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  us += mbrtowc(&c, us, es-us, s->mbstate); | 
					
						
							|  |  |  | 	  if ( c == '\r' && skip_cr(s) ) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	  if ( s->position ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    S__fupdatefilepos_getc(s, c); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  addSmallIntList(&ctx, c); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno = pos0.byteno+us-buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	re_buffer(s, us, es-us); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       case ENC_UTF8: | 
					
						
							|  |  |  |       { const char *us = buf; | 
					
						
							|  |  |  | 	const char *es = buf+n; | 
					
						
							|  |  |  | 	size_t count = 0, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(us<es) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	{ if ( !(us[0]&0x80) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  { count++; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	    us++; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  } else | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	  { int ex = UTF8_FBN(us[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( ex >= 0 ) | 
					
						
							|  |  |  | 	    { const char *ec = us + ex + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      if ( ec <= es ) | 
					
						
							|  |  |  | 	      { count++; | 
					
						
							|  |  |  | 		us=ec; | 
					
						
							|  |  |  | 	      } else			/* incomplete multi-byte */ | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	    } else | 
					
						
							|  |  |  | 	    { Sseterr(s, SIO_WARN, "Illegal multibyte Sequence"); | 
					
						
							|  |  |  | 	      goto failure; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DEBUG(2, Sdprintf("Got %ld codes from %d bytes; incomplete: %ld\n", | 
					
						
							|  |  |  | 			  count, n, es-us)); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ( !allocList(count, &ctx) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(us=buf,i=0; i<count; i++) | 
					
						
							|  |  |  | 	{ int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  us = utf8_get_char(us, &c); | 
					
						
							|  |  |  | 	  if ( c == '\r' && skip_cr(s) ) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | 	  if ( s->position ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    S__fupdatefilepos_getc(s, c); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  addSmallIntList(&ctx, c); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno = pos0.byteno+us-buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	re_buffer(s, us, es-us); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       case ENC_UNICODE_BE: | 
					
						
							|  |  |  |       case ENC_UNICODE_LE: | 
					
						
							|  |  |  |       { size_t count = (size_t)n/2; | 
					
						
							|  |  |  | 	const char *us = buf; | 
					
						
							|  |  |  | 	size_t done, i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	if ( !allocList(count, &ctx) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(i=0; i<count; us+=2, i++) | 
					
						
							|  |  |  | 	{ int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( s->encoding == ENC_UNICODE_BE ) | 
					
						
							|  |  |  | 	    c = ((us[0]&0xff)<<8)+(us[1]&0xff); | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    c = ((us[1]&0xff)<<8)+(us[0]&0xff); | 
					
						
							|  |  |  | 	  if ( c == '\r' && skip_cr(s) ) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  if ( s->position ) | 
					
						
							|  |  |  | 	    S__fupdatefilepos_getc(s, c); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  addSmallIntList(&ctx, c); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	done = count*2; | 
					
						
							|  |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno = pos0.byteno+done; | 
					
						
							|  |  |  | 	re_buffer(s, buf+done, n-done); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       case ENC_WCHAR: | 
					
						
							|  |  |  |       { const pl_wchar_t *ws = (const pl_wchar_t*)buf; | 
					
						
							|  |  |  | 	size_t count = (size_t)n/sizeof(pl_wchar_t); | 
					
						
							|  |  |  | 	size_t done, i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	if ( !allocList(count, &ctx) ) | 
					
						
							|  |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	for(i=0; i<count; i++) | 
					
						
							|  |  |  | 	{ int c = ws[i]; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  if ( c == '\r' && skip_cr(s) ) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | 	  if ( s->position ) | 
					
						
							|  |  |  | 	    S__fupdatefilepos_getc(s, c); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  addSmallIntList(&ctx, c); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	done = count*sizeof(pl_wchar_t); | 
					
						
							|  |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno = pos0.byteno+done; | 
					
						
							|  |  |  | 	re_buffer(s, buf+done, n-done); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       case ENC_UNKNOWN: | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  | 	assert(0); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |         return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     if ( !unifyDiffList(A2, A3, &ctx) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       goto failure; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     releaseStream(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   failure: | 
					
						
							|  |  |  |     Sseek64(s, off0, SIO_SEEK_SET);	/* TBD: error? */ | 
					
						
							|  |  |  |     if ( s->position ) | 
					
						
							|  |  |  |       *s->position = pos0; | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  | //! @}
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  | //! @defgroup CharsIO Character Input/Output
 | 
					
						
							|  |  |  | //  @ingroup InputOutput
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | //  @{
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							|  |  |  | put_byte(term_t stream, term_t byte ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  |   int c; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !PL_get_integer(byte, &c) || c < 0 || c > 255 ) | 
					
						
							|  |  |  |     return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_byte, byte); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getBinaryOutputStream(stream, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Sputc(c, s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return streamStatus(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  put_byte(+ _S_,+ _N_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As `put_byte(N)`, but to binary stream  _S_. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put_byte", 2, put_byte2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_byte(A1, A2 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  put_byte(+ _N_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Outputs to the current output stream the character whose code is | 
					
						
							|  |  |  |  _N_. The current output stream must be a binary stream. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put_byte", 1, put_byte1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_byte(0, A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							|  |  |  | put_code(term_t stream, term_t chr ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  |   int c = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_char(chr, &c, FALSE) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getTextOutputStream(stream, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Sputcode(c, s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return streamStatus(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  put_code(+ _S_,+ _N_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As `put_code(N)`, but to text stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | */ | 
					
						
							|  |  |  | /** @pred  put_char(+ _S_,+ _A_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As `put_char(A)`, but to text stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put_code", 2, put_code2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_code(A1, A2 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  put_char(+ _N_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Outputs to the current output stream the character who is used to build | 
					
						
							|  |  |  | the representation of atom `A`. The current output stream must be a | 
					
						
							|  |  |  | text stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  put_code(+ _N_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Outputs to the current output stream the character whose ASCII code is | 
					
						
							|  |  |  |  _N_. The current output stream must be a text stream. The character | 
					
						
							|  |  |  |  _N_ must be a legal ASCII character code, an expression yielding such | 
					
						
							|  |  |  | a code, or a list in which case only the first element is used. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put_code", 1, put_code1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_code(0, A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  put(+ _S_,+ _N_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As `put(N)`, but to stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put", 2, put2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_code(A1, A2 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  put(+ _N_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Outputs to the current output stream the character whose ASCII code is | 
					
						
							|  |  |  |  _N_. The character  _N_ must be a legal ASCII character code, an | 
					
						
							|  |  |  | expression yielding such a code, or a list in which case only the first | 
					
						
							|  |  |  | element is used. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("put", 1, put1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return put_code(0, A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							|  |  |  | get_nonblank(term_t in, term_t chr ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getTextInputStream(in, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(;;) | 
					
						
							|  |  |  |     { c = Sgetcode(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( c == EOF ) | 
					
						
							|  |  |  |       { TRY(PL_unify_integer(chr, -1)); | 
					
						
							|  |  |  | 	return streamStatus(s); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( !isBlankW(c) ) | 
					
						
							|  |  |  |       { releaseStream(s); | 
					
						
							|  |  |  | 	return PL_unify_integer(chr, c); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  get(- _C_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The next non-blank character from the current input stream is unified | 
					
						
							|  |  |  | with  _C_. Blank characters are the ones whose ASCII codes are not | 
					
						
							|  |  |  | greater than 32. If there are no more non-blank characters in the | 
					
						
							|  |  |  | stream,  _C_ is unified with -1. If `end_of_stream` has already | 
					
						
							|  |  |  | been reached in the previous reading, this call will give an error message. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get", 1, get1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return get_nonblank(0, A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  get(+ _S_,- _C_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The same as `get(C)`, but from stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get", 2, get2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return get_nonblank(A1, A2 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							|  |  |  | skip(term_t in, term_t chr ARG_LD) | 
					
						
							|  |  |  | { int c = -1; | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_char(chr, &c, FALSE) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getTextInputStream(in, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   while((r=Sgetcode(s)) != c && r != EOF ) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return streamStatus(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  skip(+ _N_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Skips input characters until the next occurrence of the character with | 
					
						
							|  |  |  | ASCII code  _N_. The argument to this predicate can take the same forms | 
					
						
							|  |  |  | as those for `put` (see 6.11). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("skip", 1, skip1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return skip(0, A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  skip(+ _S_,- _C_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Like skip/1, but using stream  _S_ instead of the current | 
					
						
							|  |  |  | input stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("skip", 2, skip2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return skip(A1, A2 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred get_single_char( +_Stream_ )
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SWI-Prolog predicate that reads the first charcter from `user_input`. | 
					
						
							|  |  |  |  * This operation is unbuffered, | 
					
						
							|  |  |  |  * and it does not have to wait for n newline. Spaces and tabulation characters are | 
					
						
							|  |  |  |  * ignored. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("get_single_char", 1, get_single_char, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s = getStream(Suser_input); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   int c; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !s ) | 
					
						
							|  |  |  |     return symbol_no_stream(ATOM_user_input); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   c = getSingleChar(s, TRUE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( c == EOF ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   { if ( PL_exception(0) ) | 
					
						
							|  |  |  |     { releaseStream(s); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_unify_integer(A1, -1); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return streamStatus(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   releaseStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return PL_unify_integer(A1, c); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | get_byte2(term_t in, term_t chr ARG_LD) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getBinaryInputStream(in, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int c = Sgetc(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( PL_unify_integer(chr, c) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( Sferror(s) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_get_char(chr, &c, TRUE);		/* set type-error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  get_byte(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is a character code, and the stream  _S_ is a | 
					
						
							|  |  |  | binary stream, read the next byte from that stream and unify its | 
					
						
							|  |  |  | code with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_byte", 2, get_byte2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return get_byte2(A1, A2 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  get_byte(- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is a character code, and the current stream is a | 
					
						
							|  |  |  | binary stream, read the next byte from the current stream and unify its | 
					
						
							|  |  |  | code with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_byte", 1, get_byte1, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return get_byte2(0, A1 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  get0(+ _S_,- _C_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The same as `get0(C)`, but from stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static foreign_t | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | get_code2(term_t in, term_t chr ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getTextInputStream(in, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int c = Sgetcode(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( PL_unify_integer(chr, c) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( Sferror(s) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_get_char(chr, &c, TRUE);		/* set type-error */ | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  get_code(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is a character code, and the stream  _S_ is a | 
					
						
							|  |  |  | text stream, read the next character from that stream and unify its | 
					
						
							|  |  |  | code with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_code", 2, get_code2, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return get_code2(A1, A2 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  get_code(- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is the code for a character, and | 
					
						
							|  |  |  | the current stream is a text stream, read the next character from the | 
					
						
							|  |  |  | current stream and unify its code with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_code", 1, get_code1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return get_code2(0, A1 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static foreign_t | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | get_char2(term_t in, term_t chr ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getTextInputStream(in, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int c = Sgetcode(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( PL_unify_atom(chr, c == -1 ? ATOM_end_of_file : codeToAtom(c)) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( Sferror(s) ) | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PL_get_char(chr, &c, TRUE);		/* set type-error */ | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  get_char(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the stream  _S_ is a text stream, read the next character from that | 
					
						
							|  |  |  | stream and unify its representation as an atom with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_char", 2, get_char2, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return get_char2(A1, A2 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  get_char(- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the current stream is a text stream, read the next character from the | 
					
						
							|  |  |  | current stream and unify its atom representation with  _C_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | PRED_IMPL("get_char", 1, get_char1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return get_char2(0, A1 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  ttyflush
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Flush the current output stream. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("ttyflush", 0, ttyflush, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s = getStream(Suser_output); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s ) | 
					
						
							|  |  |  |   { Sflush(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return streamStatus(s); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   return symbol_no_stream(ATOM_user_output); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred protocol( _File_ )
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Start protocolling user interaction to _File_, closing any previous protocolling | 
					
						
							|  |  |  |  * file and truncating it. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("protocol", 1, protocol, 0) | 
					
						
							|  |  |  | { return openProtocol(A1, FALSE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred protocola( _File_ )
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Start protocolling user interaction to _File_, closing any previous protocolling | 
					
						
							|  |  |  |  * file and then appending it. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("protocola", 1, protocola, 0) | 
					
						
							|  |  |  | { return openProtocol(A1, TRUE); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred protocolling( -_File_ )
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Report whether we are protocolling and to which _File_. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("protocolling", 1, protocolling, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s = Sprotocol) ) | 
					
						
							|  |  |  |   { atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (a = fileNameStream(s)) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return PL_unify_atom(A1, a); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return PL_unify_stream_or_alias(A1, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred prompt(- _A_,+ _B_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | Changes YAP input prompt from  _A_ to  _B_. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("prompt", 2, prompt, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t old = A1; | 
					
						
							|  |  |  |   term_t new = A2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( PL_unify_atom(old, LD->prompt.current) && | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |        PL_get_atom_ex(new, &a) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { if ( LD->prompt.current ) | 
					
						
							|  |  |  |       PL_unregister_atom(LD->prompt.current); | 
					
						
							|  |  |  |     LD->prompt.current = a; | 
					
						
							|  |  |  |     PL_register_atom(a); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred prompt1(+ _Prompt_)
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | Set the YAP input prompt for the next line. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | prompt1(atom_t prompt) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   if ( LD->prompt.first != prompt ) | 
					
						
							|  |  |  |   { if ( LD->prompt.first ) | 
					
						
							|  |  |  |       PL_unregister_atom(LD->prompt.first); | 
					
						
							|  |  |  |     LD->prompt.first = prompt; | 
					
						
							|  |  |  |     PL_register_atom(LD->prompt.first); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LD->prompt.first_used = FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("prompt1", 1, prompt1, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  |   PL_chars_t txt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   if ( PL_get_atom(A1, &a) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { prompt1(a); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   } else if ( PL_get_text(A1, &txt,  CVT_ALL|CVT_EXCEPTION) ) | 
					
						
							| 
									
										
										
										
											2015-02-13 12:20:46 +00:00
										 |  |  |     { prompt1(YAP_SWIAtomFromAtom(textToAtom(&txt))); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } else | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | atom_t | 
					
						
							|  |  |  | PrologPrompt() | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !LD->prompt.first_used && LD->prompt.first ) | 
					
						
							|  |  |  |   { LD->prompt.first_used = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return LD->prompt.first; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( Sinput->position && Sinput->position->linepos == 0 ) | 
					
						
							|  |  |  |     return LD->prompt.current; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0;				/* "" */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | tab(term_t out, term_t spaces ARG_LD) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { int64_t count; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getTextOutputStream(out, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  |   if ( !PL_eval_expression_to_int64_ex(spaces, &count) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   while(count-- > 0) | 
					
						
							|  |  |  |   { if ( Sputcode(' ', s) < 0 ) | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return streamStatus(s); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  tab(+ _S_,+ _N_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The same as tab/1, but using stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("tab", 2, tab2, 0) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return tab(A1, A2 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  tab(+ _N_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Outputs  _N_ spaces to the current output stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("tab", 1, tab1, 0) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return tab(0, A1 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      ENCODING		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static struct encname | 
					
						
							|  |  |  | { IOENC  code; | 
					
						
							|  |  |  |   atom_t name; | 
					
						
							|  |  |  | } encoding_names[] = | 
					
						
							|  |  |  | { { ENC_UNKNOWN,     ATOM_unknown }, | 
					
						
							|  |  |  |   { ENC_OCTET,       ATOM_octet }, | 
					
						
							|  |  |  |   { ENC_ASCII,       ATOM_ascii }, | 
					
						
							|  |  |  |   { ENC_ISO_LATIN_1, ATOM_iso_latin_1 }, | 
					
						
							|  |  |  |   { ENC_ANSI,	     ATOM_text }, | 
					
						
							|  |  |  |   { ENC_UTF8,        ATOM_utf8 }, | 
					
						
							|  |  |  |   { ENC_UNICODE_BE,  ATOM_unicode_be }, | 
					
						
							|  |  |  |   { ENC_UNICODE_LE,  ATOM_unicode_le }, | 
					
						
							|  |  |  |   { ENC_WCHAR,	     ATOM_wchar_t }, | 
					
						
							|  |  |  |   { ENC_UNKNOWN,     0 }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | IOENC | 
					
						
							|  |  |  | atom_to_encoding(atom_t a) | 
					
						
							|  |  |  | { struct encname *en; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(en=encoding_names; en->name; en++) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { if ( en->name == a ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return en->code; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ENC_UNKNOWN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | atom_t | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | encoding_to_atom(IOENC enc) | 
					
						
							|  |  |  | { return encoding_names[enc].name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | bad_encoding(const char *msg, atom_t name) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   term_t t = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PL_put_atom(t, name); | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   return PL_error(NULL, 0, msg, ERR_DOMAIN, ATOM_encoding, t); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | fn_to_atom() translates a 8-bit  filename  into   a  unicode  atom.  The | 
					
						
							|  |  |  | encoding is generic `multibyte' on Unix systems   and  fixed to UTF-8 on | 
					
						
							|  |  |  | Windows, where the uxnt layer  translates   the  UTF-8  sequences to the | 
					
						
							|  |  |  | Windows *W() functions. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static atom_t | 
					
						
							|  |  |  | fn_to_atom(const char *fn) | 
					
						
							|  |  |  | { PL_chars_t text; | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   text.text.t    = (char *)fn; | 
					
						
							|  |  |  |   text.encoding  = ((REP_FN&REP_UTF8) ? ENC_UTF8 : | 
					
						
							|  |  |  | 		    (REP_FN&REP_MB)   ? ENC_ANSI : ENC_ISO_LATIN_1); | 
					
						
							|  |  |  |   text.storage   = PL_CHARS_HEAP; | 
					
						
							|  |  |  |   text.length    = strlen(fn); | 
					
						
							|  |  |  |   text.canonical = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 12:20:46 +00:00
										 |  |  |   a =  YAP_SWIAtomFromAtom(textToAtom(&text)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   PL_free_text(&text); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/********************************
 | 
					
						
							|  |  |  | 		*       STREAM BASED I/O        * | 
					
						
							|  |  |  | 		*********************************/ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static const opt_spec open4_options[] = | 
					
						
							|  |  |  | { { ATOM_type,		 OPT_ATOM }, | 
					
						
							|  |  |  |   { ATOM_reposition,     OPT_BOOL }, | 
					
						
							|  |  |  |   { ATOM_alias,	         OPT_ATOM }, | 
					
						
							|  |  |  |   { ATOM_eof_action,     OPT_ATOM }, | 
					
						
							|  |  |  |   { ATOM_close_on_abort, OPT_BOOL }, | 
					
						
							|  |  |  |   { ATOM_buffer,	 OPT_ATOM }, | 
					
						
							|  |  |  |   { ATOM_lock,		 OPT_ATOM }, | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { ATOM_wait,		 OPT_BOOL }, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { ATOM_encoding,	 OPT_ATOM }, | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { ATOM_bom,		 OPT_BOOL }, | 
					
						
							| 
									
										
										
										
											2014-08-05 09:06:35 -05:00
										 |  |  |   { ATOM_scripting,	 OPT_BOOL }, | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   { ATOM_locale,	 OPT_LOCALE }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { NULL_ATOM,	         0 } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | /* MT: openStream() must be called unlocked */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | IOSTREAM * | 
					
						
							|  |  |  | openStream(term_t file, term_t mode, term_t options) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   atom_t mname; | 
					
						
							|  |  |  |   atom_t type           = ATOM_text; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   int    reposition     = TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t alias	        = NULL_ATOM; | 
					
						
							|  |  |  |   atom_t eof_action     = ATOM_eof_code; | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   int    close_on_abort = TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t buffer         = ATOM_full; | 
					
						
							|  |  |  |   atom_t lock		= ATOM_none; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   int	 wait		= TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t encoding	= NULL_ATOM; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   int	 bom		= -1; | 
					
						
							| 
									
										
										
										
											2014-08-05 09:06:35 -05:00
										 |  |  |   int	 scripting	= FALSE; | 
					
						
							| 
									
										
										
										
											2015-03-24 09:38:02 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   PL_locale *locale     = NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   char   how[10]; | 
					
						
							|  |  |  |   char  *h		= how; | 
					
						
							|  |  |  |   char *path; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   IOENC enc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( options ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { if ( !scan_options(options, 0, ATOM_stream_option, open4_options, | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		       &type, &reposition, &alias, &eof_action, | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 		       &close_on_abort, &buffer, &lock, &wait, | 
					
						
							| 
									
										
										
										
											2014-08-05 09:06:35 -05:00
										 |  |  |   &encoding, &bom, &scripting | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  | 		       , &locale | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		      ) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* MODE */ | 
					
						
							|  |  |  |   if ( PL_get_atom(mode, &mname) ) | 
					
						
							|  |  |  |   { if ( mname == ATOM_write ) | 
					
						
							|  |  |  |     { *h++ = 'w'; | 
					
						
							|  |  |  |     } else if ( mname == ATOM_append ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { *h++ = 'a'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } else if ( mname == ATOM_update ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { *h++ = 'u'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } else if ( mname == ATOM_read ) | 
					
						
							|  |  |  |     { *h++ = 'r'; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_io_mode, mode); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_atom, mode); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* ENCODING */ | 
					
						
							|  |  |  |   if ( encoding != NULL_ATOM ) | 
					
						
							|  |  |  |   { enc = atom_to_encoding(encoding); | 
					
						
							|  |  |  |     if ( enc == ENC_UNKNOWN ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     { bad_encoding(NULL, encoding); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( type == ATOM_binary && enc != ENC_OCTET ) | 
					
						
							| 
									
										
										
										
											2015-03-24 09:38:02 +00:00
										 |  |  |       { bad_encoding("type(binary) implies encoding(octet)", encoding); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     switch(enc)				/* explicitely specified: do not */ | 
					
						
							|  |  |  |     { case ENC_OCTET:			/* switch to Unicode.  For implicit */ | 
					
						
							|  |  |  |       case ENC_ASCII:			/* and unicode types we must detect */ | 
					
						
							| 
									
										
										
										
											2015-03-24 09:38:02 +00:00
										 |  |  |     case ENC_ISO_LATIN_1:		/* and skip the BOM */ | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |       case ENC_WCHAR: | 
					
						
							|  |  |  | 	bom = FALSE; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } else if ( type == ATOM_binary ) | 
					
						
							|  |  |  |   { enc = ENC_OCTET; | 
					
						
							|  |  |  |     bom = FALSE; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { enc = LD->encoding; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( bom == -1 ) | 
					
						
							|  |  |  |     bom = (mname == ATOM_read ? TRUE : FALSE); | 
					
						
							|  |  |  |   if ( type == ATOM_binary ) | 
					
						
							|  |  |  |     *h++ = 'b'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* LOCK */ | 
					
						
							|  |  |  |   if ( lock != ATOM_none ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { *h++ = (wait ? 'l' : 'L'); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( lock == ATOM_read || lock == ATOM_shared ) | 
					
						
							|  |  |  |       *h++ = 'r'; | 
					
						
							|  |  |  |     else if ( lock == ATOM_write || lock == ATOM_exclusive ) | 
					
						
							|  |  |  |       *h++ = 'w'; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { term_t l = PL_new_term_ref(); | 
					
						
							|  |  |  |       PL_put_atom(l, lock); | 
					
						
							|  |  |  |       PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_lock, l); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *h = EOS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* FILE */ | 
					
						
							|  |  |  | #ifdef HAVE_POPEN
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( PL_is_functor(file, FUNCTOR_pipe1) ) | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   { term_t a; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     char *cmd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     PL_clear_exception(); | 
					
						
							|  |  |  |     a = PL_new_term_ref(); | 
					
						
							|  |  |  |     _PL_get_arg(1, file, a); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( !PL_get_chars(a, &cmd, CVT_ATOM|CVT_STRING|REP_FN) ) | 
					
						
							|  |  |  |     { PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_atom, a); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !(s = Sopen_pipe(cmd, how)) ) | 
					
						
							|  |  |  |     { PL_error(NULL, 0, OsError(), ERR_FILE_OPERATION, | 
					
						
							|  |  |  | 	       ATOM_open, ATOM_source_sink, file); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } else | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif /*HAVE_POPEN*/
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( PL_get_file_name(file, &path, 0) ) | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  |   { | 
					
						
							|  |  |  |     if ( !(s = Sopen_file(path, how)) ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     { PL_error(NULL, 0, OsError(), ERR_FILE_OPERATION, | 
					
						
							|  |  |  | 	       ATOM_open, ATOM_source_sink, file); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     setFileNameStream_unlocked(s, fn_to_atom(path)); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } else | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->encoding = enc; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   if ( locale ) | 
					
						
							|  |  |  |   { Ssetlocale(s, locale, NULL); | 
					
						
							|  |  |  |     releaseLocale(locale);			/* acquired by scan_options() */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !close_on_abort ) | 
					
						
							|  |  |  |     s->flags |= SIO_NOCLOSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( how[0] == 'r' ) | 
					
						
							|  |  |  |   { if ( eof_action != ATOM_eof_code ) | 
					
						
							|  |  |  |     { if ( eof_action == ATOM_reset ) | 
					
						
							|  |  |  | 	s->flags |= SIO_NOFEOF; | 
					
						
							|  |  |  |       else if ( eof_action == ATOM_error ) | 
					
						
							|  |  |  | 	s->flags |= SIO_FEOF2ERR; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       else | 
					
						
							|  |  |  |       { term_t ex = PL_new_term_ref(); | 
					
						
							|  |  |  | 	PL_put_atom(ex, eof_action); | 
					
						
							|  |  |  | 	PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_eof_action, ex); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( buffer != ATOM_full ) | 
					
						
							|  |  |  |     { s->flags &= ~SIO_FBUF; | 
					
						
							|  |  |  |       if ( buffer == ATOM_line ) | 
					
						
							|  |  |  | 	s->flags |= SIO_LBUF; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       else if ( buffer == ATOM_false ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	s->flags |= SIO_NBUF; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |       else | 
					
						
							|  |  |  |       { term_t ex = PL_new_term_ref(); | 
					
						
							|  |  |  | 	PL_put_atom(ex, buffer); | 
					
						
							|  |  |  | 	PL_error(NULL, 0, NULL, ERR_DOMAIN, ATOM_buffer, ex); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( alias != NULL_ATOM ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { LOCK(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     aliasStream(s, alias); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     UNLOCK(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !reposition ) | 
					
						
							|  |  |  |     s->position = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( bom ) | 
					
						
							|  |  |  |   { if ( mname == ATOM_read ) | 
					
						
							|  |  |  |     { if ( ScheckBOM(s) < 0 ) | 
					
						
							|  |  |  |       { bom_error: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	streamStatus(getStream(s)); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-08-05 09:06:35 -05:00
										 |  |  |       if ( scripting) { | 
					
						
							|  |  |  | 	int c; | 
					
						
							|  |  |  | 	while (( c = Sgetc(s)) == '#') { | 
					
						
							|  |  |  | 	  while( (c = Sgetc(s)) != EOF && c != 10); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ( c != EOF ) | 
					
						
							|  |  |  | 	  Sungetc(c, s); | 
					
						
							|  |  |  | 	else goto bom_error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } else | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |     { if ( mname == ATOM_write || | 
					
						
							|  |  |  | 	   ( (mname == ATOM_append || mname == ATOM_update) && | 
					
						
							|  |  |  | 	     Ssize(s) == 0 ) ) | 
					
						
							|  |  |  |       { if ( SwriteBOM(s) < 0 ) | 
					
						
							|  |  |  | 	  goto bom_error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred open(+ _F_,+ _M_,- _S_,+ _Opts_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Opens the file with name  _F_ in mode  _M_ (`read`,  `write` or | 
					
						
							|  |  |  | `append`), returning  _S_ unified with the stream name, and following | 
					
						
							|  |  |  | these options: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `type(+ _T_)` is iso | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Specify whether the stream is a `text` stream (default), or a | 
					
						
							|  |  |  | `binary` stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `reposition(+ _Bool_)` is iso | 
					
						
							|  |  |  |   Specify whether it is possible to reposition the stream (`true`), or | 
					
						
							|  |  |  | not (`false`). By default, YAP enables repositioning for all | 
					
						
							|  |  |  | files, except terminal files and sockets. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `eof(+ _Action_)` is iso | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Specify the action to take if attempting to input characters from a | 
					
						
							|  |  |  | stream where we have previously found an `end_of_file`. The possible | 
					
						
							|  |  |  | actions are `error`, that raises an error, `reset`, that tries to | 
					
						
							|  |  |  | reset the stream and is used for `tty` type files, and `eof_code`, | 
					
						
							|  |  |  | which generates a new `end_of_file` (default for non-tty files). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `alias(+ _Name_)` is iso | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Specify an alias to the stream. The alias <tt>Name</tt> must be an atom. The | 
					
						
							|  |  |  | alias can be used instead of the stream descriptor for every operation | 
					
						
							|  |  |  | concerning the stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The operation will fail and give an error if the alias name is already | 
					
						
							|  |  |  | in use. YAP allows several aliases for the same file, but only | 
					
						
							|  |  |  | one is returned by stream_property/2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `bom(+ _Bool_)` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If present and `true`, a BOM (<em>Byte Order Mark</em>) was | 
					
						
							|  |  |  | detected while opening the file for reading or a BOM was written while | 
					
						
							|  |  |  | opening the stream. See BOM for details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `encoding(+ _Encoding_)` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Set the encoding used for text.  See Encoding for an overview of | 
					
						
							|  |  |  | wide character and encoding issues. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `representation_errors(+ _Mode_)` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Change the behaviour when writing characters to the stream that cannot | 
					
						
							|  |  |  | be represented by the encoding.  The behaviour is one of `error` | 
					
						
							|  |  |  | (throw and Input/Output error exception), `prolog` (write `\u...\` | 
					
						
							|  |  |  | escape code or `xml` (write `\&#...;` XML character entity). | 
					
						
							|  |  |  | The initial mode is `prolog` for the user streams and | 
					
						
							|  |  |  | `error` for all other streams. See also Encoding. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + `expand_filename(+ _Mode_)` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If  _Mode_ is `true` then do filename expansion, then ask Prolog | 
					
						
							|  |  |  | to do file name expansion before actually trying to opening the file: | 
					
						
							|  |  |  | this includes processing `~` characters and processing `$` | 
					
						
							|  |  |  | environment variables at the beginning of the file. Otherwise, just try | 
					
						
							|  |  |  | to open the file using the given name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The default behavior is given by the Prolog flag | 
					
						
							|  |  |  | open_expands_filename. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("open", 4, open4, PL_FA_ISO) | 
					
						
							|  |  |  | { IOSTREAM *s = openStream(A1, A2, A4); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( s ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return PL_unify_stream_or_alias(A3, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  open(+ _F_,+ _M_,- _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Opens the file with name  _F_ in mode  _M_ (`read`, `write` or | 
					
						
							|  |  |  | `append`), returning  _S_ unified with the stream name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | At most, there are 17 streams  opened at the same time. Each stream is | 
					
						
							|  |  |  | either an input or an output stream but not both. There are always 3 | 
					
						
							|  |  |  | open streams:  user_input for reading, user_output for writing | 
					
						
							|  |  |  | and user_error for writing. If there is no  ambiguity, the atoms | 
					
						
							|  |  |  | user_input and user_output may be referred to as  `user`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `file_errors` flag controls whether errors are reported when in | 
					
						
							|  |  |  | mode `read` or `append` the file  _F_ does not exist or is not | 
					
						
							|  |  |  | readable, and whether in mode `write` or `append` the file is not | 
					
						
							|  |  |  | writable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("open", 3, open3, PL_FA_ISO) | 
					
						
							|  |  |  | { IOSTREAM *s = openStream(A1, A2, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s ) | 
					
						
							|  |  |  |     return PL_unify_stream_or_alias(A3, s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  | //! @}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @defgroup DEC10_IO DEC-10/C-Prolog Compatible File Handling
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  |  * @ingroup InputOutput | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	  EDINBURGH I/O		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static IOSTREAM * | 
					
						
							|  |  |  | findStreamFromFile(atom_t name, unsigned int flags) | 
					
						
							|  |  |  | { TableEnum e; | 
					
						
							|  |  |  |   Symbol symb; | 
					
						
							|  |  |  |   IOSTREAM *s = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   e = newTableEnum(streamContext); | 
					
						
							|  |  |  |   while( (symb=advanceTableEnum(e)) ) | 
					
						
							|  |  |  |   { stream_context *ctx = symb->value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( ctx->filename == name && | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  | 	 True(ctx, flags) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { s = symb->name; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   freeTableEnum(e); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | pl_see(term_t f) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  |   term_t mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !PL_get_atom_ex(f, &a) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   PL_LOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( get_stream_handle(a, &s, SH_ALIAS|SH_UNLOCKED) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurin = s; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( a == ATOM_user ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurin = Suser_input; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( (s = findStreamFromFile(a, IO_SEE)) ) | 
					
						
							|  |  |  |   { Scurin = s; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mode = PL_new_term_ref(); | 
					
						
							|  |  |  |   PL_put_atom(mode, ATOM_read); | 
					
						
							|  |  |  |   if ( !(s = openStream(f, mode, 0)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { PL_UNLOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   set(getStreamContext(s), IO_SEE); | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   push_input_context(ATOM_see); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Scurin = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ok: | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   PL_UNLOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2011-02-10 00:02:05 +00:00
										 |  |  | pl_seen(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s = getStream(Scurin); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   pop_input_context(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  |   if ( s && (s->flags & SIO_NOFEOF) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s ) | 
					
						
							|  |  |  |     return closeStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return symbol_no_stream(ATOM_current_input); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  see(+ _S_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _S_ is a currently opened input stream then it is assumed to be | 
					
						
							|  |  |  | the current input stream. If  _S_ is an atom it is taken as a | 
					
						
							|  |  |  | filename. If there is no input stream currently associated with it, then | 
					
						
							|  |  |  | it is opened for input, and the new input stream thus created becomes | 
					
						
							|  |  |  | the current input stream. If it is not possible to open the file, an | 
					
						
							|  |  |  | error occurs.  If there is a single opened input stream currently | 
					
						
							|  |  |  | associated with the file, it becomes the current input stream; if there | 
					
						
							|  |  |  | are more than one in that condition, then one of them is chosen. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When  _S_ is a stream not currently opened for input, an error may be | 
					
						
							|  |  |  | reported, depending on the state of the `file_errors` flag. If | 
					
						
							|  |  |  |  _S_ is neither a stream nor an atom the predicates just fails. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("see", 1, see, 0) | 
					
						
							|  |  |  | { return pl_see(A1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  seen
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Closes the current input stream (see 6.7.). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("seen", 0, seen, 0) | 
					
						
							|  |  |  | { return pl_seen(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  seeing(- _S_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The current input stream is unified with  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("seeing", 1, seeing, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( Scurin == Suser_input ) | 
					
						
							|  |  |  |     return PL_unify_atom(A1, ATOM_user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_stream(A1, Scurin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | /* MT: Does not create a lock on the stream
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | do_tell(term_t f, atom_t m) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   atom_t a; | 
					
						
							|  |  |  |   term_t mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !PL_get_atom_ex(f, &a) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   PL_LOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( get_stream_handle(a, &s, SH_UNLOCKED) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurout = s; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( a == ATOM_user ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurout = Suser_output; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( (s = findStreamFromFile(a, IO_TELL)) ) | 
					
						
							|  |  |  |   { Scurout = s; | 
					
						
							|  |  |  |     goto ok; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mode = PL_new_term_ref(); | 
					
						
							|  |  |  |   PL_put_atom(mode, m); | 
					
						
							|  |  |  |   if ( !(s = openStream(f, mode, 0)) ) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   { PL_UNLOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   set(getStreamContext(s), IO_TELL); | 
					
						
							|  |  |  |   pushOutputContext(); | 
					
						
							|  |  |  |   Scurout = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ok: | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   PL_UNLOCK(L_SEETELL); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  tell(+ _S_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _S_ is a currently opened stream for output, it becomes the | 
					
						
							|  |  |  | current output stream. If  _S_ is an atom it is taken to be a | 
					
						
							|  |  |  | filename.  If there is no output stream currently associated with it, | 
					
						
							|  |  |  | then it is opened for output, and the new output stream created becomes | 
					
						
							|  |  |  | the current output stream. If it is not possible to open the file, an | 
					
						
							|  |  |  | error occurs.  If there is a single opened output stream currently | 
					
						
							|  |  |  | associated with the file, then it becomes the current output stream; if | 
					
						
							|  |  |  | there are more than one in that condition, one of them is chosen. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Whenever  _S_ is a stream not currently opened for output, an error | 
					
						
							|  |  |  | may be reported, depending on the state of the file_errors flag. The | 
					
						
							|  |  |  | predicate just fails, if  _S_ is neither a stream nor an atom. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("tell", 1, tell, 0) | 
					
						
							|  |  |  | { return do_tell(A1, ATOM_write); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("append", 1, append, 0) | 
					
						
							|  |  |  | { return do_tell(A1, ATOM_append); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  telling(- _S_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The current output stream is unified with  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("telling", 1, telling, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( Scurout == Suser_output ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return PL_unify_atom(A1, ATOM_user); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return PL_unify_stream(A1, Scurout); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  told
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Closes the current output stream, and the user's terminal becomes again | 
					
						
							|  |  |  | the current output stream. It is important to remember to close streams | 
					
						
							|  |  |  | after having finished using them, as the maximum number of | 
					
						
							|  |  |  | simultaneously opened streams is 17. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("told", 0, told, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s = getStream(Scurout); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   popOutputContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  |   if ( s && (s->flags & SIO_NOFEOF) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s ) | 
					
						
							|  |  |  |     return closeStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return symbol_no_stream(ATOM_current_output); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  | //! @defgroup Stream Opening and Closing Streams
 | 
					
						
							|  |  |  | //  @ingroup InputOutput
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | //  @{
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	   NULL-STREAM		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_null(void *handle, char *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  |   (void)buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return size; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_null(void *handle, char *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  |   (void)buf; | 
					
						
							|  |  |  |   (void)size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | Sseek_null(void *handle, long offset, int whence) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(whence) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { case SIO_SEEK_SET: | 
					
						
							|  |  |  | 	return offset; | 
					
						
							|  |  |  |     case SIO_SEEK_CUR: | 
					
						
							|  |  |  |     case SIO_SEEK_END: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_null(void *handle) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const IOFUNCTIONS nullFunctions = | 
					
						
							|  |  |  | { Sread_null, | 
					
						
							|  |  |  |   Swrite_null, | 
					
						
							|  |  |  |   Sseek_null, | 
					
						
							|  |  |  |   Sclose_null | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("open_null_stream", 1, open_null_stream, 0) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { int sflags = SIO_NBUF|SIO_RECORDPOS|SIO_OUTPUT|SIO_TEXT; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s = Snew((void *)NULL, sflags, (IOFUNCTIONS *)&nullFunctions); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s ) | 
					
						
							|  |  |  |   { s->encoding = ENC_UTF8; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return PL_unify_stream_or_alias(A1, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | do_close(IOSTREAM *s, int force) | 
					
						
							|  |  |  | { if ( force ) | 
					
						
							|  |  |  |   { if ( !s ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |     if ( s == Sinput ) | 
					
						
							|  |  |  |       Sclearerr(s); | 
					
						
							|  |  |  |     else if ( s == Soutput || s == Serror ) | 
					
						
							|  |  |  |     { Sflush(s); | 
					
						
							|  |  |  |       Sclearerr(s); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { Sflush(s); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       if ( Sclose(s) < 0 ) | 
					
						
							|  |  |  | 	PL_clear_exception(); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else if ( s ) | 
					
						
							|  |  |  |   { return closeStream(s); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | pl_close(term_t stream, int force ARG_LD) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   atom_t a; | 
					
						
							|  |  |  |   stream_ref *ref; | 
					
						
							|  |  |  |   PL_blob_t *type; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( !PL_get_atom(stream, &a) ) | 
					
						
							|  |  |  |     return not_a_stream(stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ref = PL_blob_data(a, NULL, &type); | 
					
						
							|  |  |  |   if ( type == &stream_blob ) | 
					
						
							|  |  |  |   { int rc = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( ref->read ) | 
					
						
							|  |  |  |       rc = do_close(getStream(ref->read), force); | 
					
						
							|  |  |  |     if ( ref->write ) | 
					
						
							|  |  |  |       rc = rc && do_close(getStream(ref->write), force); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( get_stream_handle(a, &s, SH_ERRORS|SH_ALIAS) ) | 
					
						
							|  |  |  |     return do_close(s, force); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  close(+ _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Closes the stream  _S_. If  _S_ does not stand for a stream | 
					
						
							|  |  |  | currently opened an error is reported. The streams user_input, | 
					
						
							|  |  |  | user_output, and user_error can never be closed. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("close", 1, close, PL_FA_ISO) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return pl_close(A1, FALSE PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static const opt_spec close2_options[] = | 
					
						
							|  |  |  | { { ATOM_force,		 OPT_BOOL }, | 
					
						
							|  |  |  |   { NULL_ATOM,		 0 } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  close(+ _S_,+ _O_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | Closes the stream  _S_, following options  _O_. | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | The only valid options are `force(true)` and `force(false)`. | 
					
						
							|  |  |  | YAP currently ignores these options. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("close", 2, close2, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   int force = FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   if ( !scan_options(A2, 0, ATOM_close_option, close2_options, &force) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   return pl_close(A1, force PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	 STREAM-PROPERTY	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_file_name_propery(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   for(; s; s=s->downstream) | 
					
						
							|  |  |  |   { if ( (name = getStreamContext(s)->filename) ) | 
					
						
							|  |  |  |     { return PL_unify_atom(prop, name); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_mode_property(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t mode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_INPUT ) | 
					
						
							|  |  |  |     mode = ATOM_read; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { assert(s->flags & SIO_OUTPUT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( s->flags & SIO_APPEND ) | 
					
						
							|  |  |  |       mode = ATOM_append; | 
					
						
							|  |  |  |     else if ( s->flags & SIO_UPDATE ) | 
					
						
							|  |  |  |       mode = ATOM_update; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       mode = ATOM_write; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_atom(prop, mode); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_input_prop(IOSTREAM *s ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (s->flags & SIO_INPUT) ? TRUE : FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_output_prop(IOSTREAM *s ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (s->flags & SIO_OUTPUT) ? TRUE : FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Incomplete: should be non-deterministic if the stream has multiple aliases! | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_alias_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t name; | 
					
						
							|  |  |  |   stream_context *ctx = getStreamContext(s); | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( PL_get_atom(prop, &name) ) | 
					
						
							|  |  |  |   { alias *a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for( a = ctx->alias_head; a; a = a->next ) | 
					
						
							|  |  |  |     { if ( a->name == name ) | 
					
						
							|  |  |  | 	return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( (i=standardStreamIndexFromName(name)) >= 0 && | 
					
						
							|  |  |  | 	 i < 6 && | 
					
						
							|  |  |  | 	 s == LD->IO.streams[i] ) | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (i=standardStreamIndexFromStream(s)) >= 0 && i < 3 ) | 
					
						
							|  |  |  |     return PL_unify_atom(prop, standardStreams[i]); | 
					
						
							|  |  |  |   if ( ctx->alias_head ) | 
					
						
							|  |  |  |     return PL_unify_atom(prop, ctx->alias_head->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_position_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->position ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { return PL_unify_term(prop, | 
					
						
							|  |  |  | 			 PL_FUNCTOR, FUNCTOR_stream_position4, | 
					
						
							|  |  |  | 			   PL_INT64, s->position->charno, | 
					
						
							|  |  |  | 			   PL_INT, s->position->lineno, | 
					
						
							|  |  |  | 			   PL_INT, s->position->linepos, | 
					
						
							|  |  |  | 			   PL_INT64, s->position->byteno); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_end_of_stream_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { if ( s->flags & SIO_INPUT ) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   { atom_t val; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( s->flags & SIO_FEOF2 ) | 
					
						
							|  |  |  |       val = ATOM_past; | 
					
						
							|  |  |  |     else if ( s->flags & SIO_FEOF ) | 
					
						
							|  |  |  |       val = ATOM_at; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       val = ATOM_not; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PL_unify_atom(prop, val); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_eof_action_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_NOFEOF ) | 
					
						
							|  |  |  |     val = ATOM_reset; | 
					
						
							|  |  |  |   else if ( s->flags & SIO_FEOF2ERR ) | 
					
						
							|  |  |  |     val = ATOM_error; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     val = ATOM_eof_code; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_atom(prop, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_FSTAT
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(S_ISREG) && defined(S_IFREG)
 | 
					
						
							|  |  |  | #define S_ISREG(m) ((m&S_IFMT) == S_IFREG)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_reposition_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->functions->seek ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  | #ifdef HAVE_FSTAT
 | 
					
						
							|  |  |  |     int fd = Sfileno(s); | 
					
						
							|  |  |  |     struct stat buf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |     if ( fd != -1 && fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       val = ATOM_true; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       val = ATOM_false; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     val = ATOM_true; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     val = ATOM_false; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return PL_unify_atom(prop, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_close_on_abort_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_bool_ex(prop, !(s->flags & SIO_NOCLOSE)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_type_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { return PL_unify_atom(prop, s->flags & SIO_TEXT ? ATOM_text : ATOM_binary); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_file_no_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (fd = Sfileno(s)) >= 0 ) | 
					
						
							|  |  |  |     return PL_unify_integer(prop, fd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_tty_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_ISATTY) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return PL_unify_bool_ex(prop, TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_bom_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { IGNORE_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_BOM) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return PL_unify_bool_ex(prop, TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_newline_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { switch ( s->newline ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { case SIO_NL_POSIX: | 
					
						
							|  |  |  |     case SIO_NL_DETECT: | 
					
						
							|  |  |  |       return PL_unify_atom(prop, ATOM_posix); | 
					
						
							|  |  |  |     case SIO_NL_DOS: | 
					
						
							|  |  |  |       return PL_unify_atom(prop, ATOM_dos); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_encoding_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { return PL_unify_atom(prop, encoding_to_atom(s->encoding)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_locale_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { if ( s->locale ) | 
					
						
							|  |  |  |     return unifyLocale(prop, s->locale, TRUE); | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | stream_reperror_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_REPXML) ) | 
					
						
							|  |  |  |     a = ATOM_xml; | 
					
						
							|  |  |  |   else if ( (s->flags & SIO_REPPL) ) | 
					
						
							|  |  |  |     a = ATOM_prolog; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     a = ATOM_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_atom(prop, a); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_buffer_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { atom_t b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_FBUF ) | 
					
						
							|  |  |  |     b = ATOM_full; | 
					
						
							|  |  |  |   else if ( s->flags & SIO_LBUF ) | 
					
						
							|  |  |  |     b = ATOM_line; | 
					
						
							|  |  |  |   else /*if ( s->flags & SIO_NBUF )*/ | 
					
						
							|  |  |  |     b = ATOM_false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_atom(prop, b); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_buffer_size_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { if ( (s->flags & SIO_NBUF) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return PL_unify_integer(prop, s->bufsize); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stream_timeout_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { if ( s->timeout == -1 ) | 
					
						
							|  |  |  |     return PL_unify_atom(prop, ATOM_infinite); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return PL_unify_float(prop, (double)s->timeout/1000.0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | stream_nlink_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | { int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (fd = Sfileno(s)) >= 0 ) | 
					
						
							|  |  |  |   { struct stat buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( fstat(fd, &buf) == 0 ) | 
					
						
							|  |  |  |     { return PL_unify_integer(prop, buf.st_nlink); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | stream_close_on_exec_prop(IOSTREAM *s, term_t prop ARG_LD) | 
					
						
							|  |  |  | {  int fd; | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |    DWORD Flags; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |    int fd_flags; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |    IGNORE_LD | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    if ( (fd = Sfileno(s)) < 0) | 
					
						
							|  |  |  |      return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #if defined(F_GETFD) && defined(FD_CLOEXEC)
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    if ( (fd_flags = fcntl(fd, F_GETFD)) == -1) | 
					
						
							|  |  |  |      return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    return PL_unify_bool_ex(prop, (fd_flags&FD_CLOEXEC) != 0 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined __WINDOWS__
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if ( GetHandleInformation((HANDLE)_get_osfhandle(fd), &Flags) == 0 ) | 
					
						
							|  |  |  |      return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    return PL_unify_bool_ex(prop, (Flags & HANDLE_FLAG_INHERIT) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | typedef struct | 
					
						
							|  |  |  | { functor_t functor;			/* functor of property */ | 
					
						
							| 
									
										
										
										
											2011-03-02 23:19:39 +00:00
										 |  |  |   property_t function; /* function to generate */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } sprop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static const sprop sprop_list [] = | 
					
						
							|  |  |  | { { FUNCTOR_file_name1,	    stream_file_name_propery }, | 
					
						
							|  |  |  |   { FUNCTOR_mode1,	    stream_mode_property }, | 
					
						
							| 
									
										
										
										
											2011-03-02 23:19:39 +00:00
										 |  |  |   { FUNCTOR_input0,	    (property_t)stream_input_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_output0,	    (property_t)stream_output_prop }, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { FUNCTOR_alias1,	    stream_alias_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_position1,	    stream_position_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_end_of_stream1, stream_end_of_stream_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_eof_action1,    stream_eof_action_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_reposition1,    stream_reposition_prop }, | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   { FUNCTOR_type1,	    stream_type_prop }, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { FUNCTOR_file_no1,	    stream_file_no_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_buffer1,	    stream_buffer_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_buffer_size1,   stream_buffer_size_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_close_on_abort1,stream_close_on_abort_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_tty1,	    stream_tty_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_encoding1,	    stream_encoding_prop }, | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   { FUNCTOR_locale1,	    stream_locale_prop }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { FUNCTOR_bom1,	    stream_bom_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_newline1,	    stream_newline_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_representation_errors1, stream_reperror_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_timeout1,       stream_timeout_prop }, | 
					
						
							|  |  |  |   { FUNCTOR_nlink1,         stream_nlink_prop }, | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { FUNCTOR_close_on_exec1, stream_close_on_exec_prop }, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   { 0,			    NULL } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { TableEnum e;				/* Enumerator on stream-table */ | 
					
						
							|  |  |  |   IOSTREAM *s;				/* Stream we are enumerating */ | 
					
						
							|  |  |  |   const sprop *p;			/* Pointer in properties */ | 
					
						
							|  |  |  |   int fixed_p;				/* Propety is given */ | 
					
						
							|  |  |  | } prop_enum; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  stream_property(? _Stream_,? _Prop_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Obtain the properties for the open streams. If the first argument is | 
					
						
							|  |  |  | unbound, the procedure will backtrack through all open | 
					
						
							|  |  |  | streams. Otherwise, the first argument must be a stream term (you may | 
					
						
							|  |  |  | use `current_stream` to obtain a current stream given a file name). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following properties are recognized: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + file_name( _P_) | 
					
						
							|  |  |  | An atom giving the file name for the current stream. The file names are | 
					
						
							|  |  |  | user_input, user_output, and user_error for the | 
					
						
							|  |  |  | standard streams. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + mode( _P_) | 
					
						
							|  |  |  | The mode used to open the file. It may be one of `append`, | 
					
						
							|  |  |  | `read`, or `write`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + input | 
					
						
							|  |  |  | The stream is readable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + output | 
					
						
							|  |  |  | The stream is writable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + alias( _A_) | 
					
						
							|  |  |  | ISO-Prolog primitive for stream aliases. <tt>YAP</tt> returns one of the | 
					
						
							|  |  |  | existing aliases for the stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + position( _P_) | 
					
						
							|  |  |  | A term describing the position in the stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + end_of_stream( _E_) | 
					
						
							|  |  |  | Whether the stream is `at` the end of stream, or it has found the | 
					
						
							|  |  |  | end of stream and is `past`, or whether it has `not` yet | 
					
						
							|  |  |  | reached the end of stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + eof_action( _A_) | 
					
						
							|  |  |  | The action to take when trying to read after reaching the end of | 
					
						
							|  |  |  | stream. The action may be one of `error`, generate an error, | 
					
						
							|  |  |  | `eof_code`, return character code `-1`, or `reset` the | 
					
						
							|  |  |  | stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + reposition( _B_) | 
					
						
							|  |  |  | Whether the stream can be repositioned or not, that is, whether it is | 
					
						
							|  |  |  | seekable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + type( _T_) | 
					
						
							|  |  |  | Whether the stream is a `text` stream or a `binary` stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + bom(+ _Bool_) | 
					
						
							|  |  |  | If present and `true`, a BOM (<em>Byte Order Mark</em>) was | 
					
						
							|  |  |  | detected while opening the file for reading or a BOM was written while | 
					
						
							|  |  |  | opening the stream. See BOM for details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + encoding(+ _Encoding_) | 
					
						
							|  |  |  | Query the encoding used for text.  See Encoding for an | 
					
						
							|  |  |  | overview of wide character and encoding issues in YAP. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | + representation_errors(+ _Mode_) | 
					
						
							|  |  |  | Behaviour when writing characters to the stream that cannot be | 
					
						
							|  |  |  | represented by the encoding.  The behaviour is one of `error` | 
					
						
							|  |  |  | (throw and Input/Output error exception), `prolog` (write `\u...\` | 
					
						
							|  |  |  | escape code or `xml` (write `\&#...;` XML character entity). | 
					
						
							|  |  |  | The initial mode is `prolog` for the user streams and | 
					
						
							|  |  |  | `error` for all other streams. See also Encoding and | 
					
						
							|  |  |  | `open/4`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | + current_line_number(- _LineNumber_) | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _LineNumber_ with the line number for the current stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("stream_property", 2, stream_property, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	  PL_FA_ISO|PL_FA_NONDETERMINISTIC) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   prop_enum *pe; | 
					
						
							|  |  |  |   fid_t fid; | 
					
						
							|  |  |  |   term_t a1; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   atom_t a; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t stream = A1; | 
					
						
							|  |  |  |   term_t property = A2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch( CTX_CNTRL ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { case FRG_FIRST_CALL: | 
					
						
							|  |  |  |       a1 = PL_new_term_ref(); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( PL_is_variable(stream) )	/* generate */ | 
					
						
							|  |  |  |       {	const sprop *p = sprop_list; | 
					
						
							|  |  |  | 	int fixed = FALSE; | 
					
						
							|  |  |  | 	functor_t f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( PL_get_functor(property, &f) ) /* test for defined property */ | 
					
						
							|  |  |  | 	{ for( ; p->functor; p++ ) | 
					
						
							|  |  |  | 	  { if ( f == p->functor ) | 
					
						
							|  |  |  | 	    { fixed = TRUE; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  if ( !p->functor ) | 
					
						
							|  |  |  | 	    return PL_error(NULL, 0, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 			    ATOM_stream_property, property); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | 	pe = allocForeignState(sizeof(*pe)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pe->e = newTableEnum(streamContext); | 
					
						
							|  |  |  | 	pe->s = NULL; | 
					
						
							|  |  |  | 	pe->p = p; | 
					
						
							|  |  |  | 	pe->fixed_p = fixed; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       if ( !PL_get_atom(stream, &a) ) | 
					
						
							|  |  |  | 	return not_a_stream(stream); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       LOCK();				/* given stream */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       if ( get_stream_handle(a, &s, SH_ERRORS|SH_UNLOCKED) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       { functor_t f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( PL_is_variable(property) )	/* generate properties */ | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | 	{ pe = allocForeignState(sizeof(*pe)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  pe->e = NULL; | 
					
						
							|  |  |  | 	  pe->s = s; | 
					
						
							|  |  |  | 	  pe->p = sprop_list; | 
					
						
							|  |  |  | 	  pe->fixed_p = FALSE; | 
					
						
							|  |  |  | 	  UNLOCK(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	if ( PL_get_functor(property, &f) ) | 
					
						
							|  |  |  | 	{ const sprop *p = sprop_list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  for( ; p->functor; p++ ) | 
					
						
							|  |  |  | 	  { if ( f == p->functor ) | 
					
						
							|  |  |  | 	    { int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      switch(arityFunctor(f)) | 
					
						
							|  |  |  | 	      { case 0: | 
					
						
							| 
									
										
										
										
											2011-03-02 23:19:39 +00:00
										 |  |  | 		  rval = (*(property0_t)p->function)(s PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		  break; | 
					
						
							|  |  |  | 		case 1: | 
					
						
							|  |  |  | 		{ term_t a1 = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		  _PL_get_arg(1, property, a1); | 
					
						
							|  |  |  | 		  rval = (*p->function)(s, a1 PASS_LD); | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 		  assert(0); | 
					
						
							|  |  |  | 		  rval = FALSE; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	      UNLOCK(); | 
					
						
							|  |  |  | 	      return rval; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 	{ UNLOCK(); | 
					
						
							|  |  |  | 	  return PL_error(NULL, 0, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 			  ATOM_stream_property, property); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       UNLOCK(); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE;				/* bad stream handle */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     case FRG_REDO: | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     { pe = CTX_PTR; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       a1 = PL_new_term_ref(); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case FRG_CUTTED: | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     { pe = CTX_PTR; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if ( pe )				/* 0 if exception on FRG_FIRST_CALL */ | 
					
						
							|  |  |  |       { if ( pe->e ) | 
					
						
							|  |  |  | 	  freeTableEnum(pe->e); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | 	freeForeignState(pe, sizeof(*pe)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       assert(0); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   if ( !(fid = PL_open_foreign_frame()) ) | 
					
						
							|  |  |  |   { error: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( pe->e ) | 
					
						
							|  |  |  |       freeTableEnum(pe->e); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |     freeForeignState(pe, sizeof(*pe)); | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { if ( pe->s )				/* given stream */ | 
					
						
							|  |  |  |     { fid_t fid2; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( PL_is_variable(stream) ) | 
					
						
							|  |  |  |       { if ( !PL_unify_stream(stream, pe->s) ) | 
					
						
							|  |  |  | 	  goto enum_e; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |       if ( !(fid2 = PL_open_foreign_frame()) ) | 
					
						
							|  |  |  | 	goto error; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       for( ; pe->p->functor ; pe->p++ ) | 
					
						
							|  |  |  |       { if ( PL_unify_functor(property, pe->p->functor) ) | 
					
						
							|  |  |  | 	{ int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  switch(arityFunctor(pe->p->functor)) | 
					
						
							|  |  |  | 	  { case 0: | 
					
						
							| 
									
										
										
										
											2011-03-02 23:19:39 +00:00
										 |  |  | 	      rval = (*(property0_t)pe->p->function)(pe->s PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	      break; | 
					
						
							|  |  |  | 	    case 1: | 
					
						
							|  |  |  | 	    { _PL_get_arg(1, property, a1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      rval = (*pe->p->function)(pe->s, a1 PASS_LD); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    default: | 
					
						
							|  |  |  | 	      assert(0); | 
					
						
							|  |  |  | 	      rval = FALSE; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  if ( rval ) | 
					
						
							|  |  |  | 	  { if ( pe->fixed_p ) | 
					
						
							|  |  |  | 	      pe->s = NULL; | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | 	      pe->p++; | 
					
						
							|  |  |  | 	    ForeignRedoPtr(pe); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 	if ( exception_term ) | 
					
						
							|  |  |  | 	  goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	if ( pe->fixed_p ) | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	PL_rewind_foreign_frame(fid2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       PL_close_foreign_frame(fid2); | 
					
						
							|  |  |  |       pe->s = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   enum_e: | 
					
						
							|  |  |  |     if ( pe->e ) | 
					
						
							|  |  |  |     { Symbol symb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       while ( (symb=advanceTableEnum(pe->e)) ) | 
					
						
							|  |  |  |       { PL_rewind_foreign_frame(fid); | 
					
						
							|  |  |  | 	if ( PL_unify_stream(stream, symb->name) ) | 
					
						
							|  |  |  | 	{ pe->s = symb->name; | 
					
						
							|  |  |  | 	  if ( !pe->fixed_p ) | 
					
						
							|  |  |  | 	    pe->p = sprop_list; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 	if ( exception_term ) | 
					
						
							|  |  |  | 	  goto error; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !pe->s ) | 
					
						
							|  |  |  |     { if ( pe->e ) | 
					
						
							|  |  |  | 	freeTableEnum(pe->e); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |       freeForeignState(pe, sizeof(*pe)); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  is_stream( _S_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Succeeds if  _S_ is a currently open stream. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("is_stream", 1, is_stream, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   atom_t a; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( PL_get_atom(A1, &a) && | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |        get_stream_handle(a, &s, SH_UNLOCKED) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      FLUSH		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-12-24 15:32:29 +00:00
										 |  |  |  * @ingroup StreamM | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | flush_output(term_t out ARG_LD) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getOutputStream(out, S_DONTCARE, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Sflush(s); | 
					
						
							|  |  |  |     return streamStatus(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  flush_output is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Send out all data in the output buffer of the current output stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("flush_output", 0, flush_output, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return flush_output(0 PASS_LD); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  flush_output(+ _S_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Send all data in the output buffer for stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("flush_output", 1, flush_output1, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return flush_output(A1 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-12-24 15:32:29 +00:00
										 |  |  |  * @ingroup Stream | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | getStreamWithPosition(term_t stream, IOSTREAM **sp) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_stream_handle(stream, &s) ) | 
					
						
							|  |  |  |   { if ( !s->position ) | 
					
						
							|  |  |  |     { PL_error(NULL, 0, NULL, ERR_PERMISSION, /* non-ISO */ | 
					
						
							|  |  |  | 	       ATOM_property, ATOM_position, stream); | 
					
						
							|  |  |  |       releaseStream(s); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *sp = s; | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | getRepositionableStream(term_t stream, IOSTREAM **sp) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_atom(stream, &a) ) | 
					
						
							|  |  |  |     return not_a_stream(stream); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( get_stream_handle(a, &s, SH_ERRORS) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { if ( !s->position || !s->functions || !s->functions->seek ) | 
					
						
							|  |  |  |     { PL_error(NULL, 0, NULL, ERR_PERMISSION, | 
					
						
							|  |  |  | 	       ATOM_reposition, ATOM_stream, stream); | 
					
						
							|  |  |  |       releaseStream(s); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *sp = s; | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  set_stream_position(+ _S_, + _POS_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Given a stream position  _POS_ for a stream  _S_, set the current | 
					
						
							|  |  |  | stream position for  _S_ to be  _POS_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_stream_position", 2, set_stream_position, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   IOSTREAM *s = NULL;			/* make compiler happy */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int64_t charno, byteno; | 
					
						
							|  |  |  |   long linepos, lineno; | 
					
						
							|  |  |  |   term_t a = PL_new_term_ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t stream = A1; | 
					
						
							|  |  |  |   term_t pos = A2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !(getRepositionableStream(stream, &s)) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_is_functor(pos, FUNCTOR_stream_position4) || | 
					
						
							|  |  |  |        !PL_get_arg(1, pos, a) || | 
					
						
							|  |  |  |        !PL_get_int64(a, &charno) || | 
					
						
							|  |  |  |        !PL_get_arg(2, pos, a) || | 
					
						
							|  |  |  |        !PL_get_long(a, &lineno) || | 
					
						
							|  |  |  |        !PL_get_arg(3, pos, a) || | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |        !PL_get_long(a, &linepos) || | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |        !PL_get_arg(4, pos, a) || | 
					
						
							|  |  |  |        !PL_get_int64(a, &byteno) ) | 
					
						
							|  |  |  |   { releaseStream(s); | 
					
						
							|  |  |  |     return PL_error("stream_position", 3, NULL, | 
					
						
							|  |  |  | 		    ERR_DOMAIN, ATOM_stream_position, pos); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( Sseek64(s, byteno, SIO_SEEK_SET) != 0 ) | 
					
						
							|  |  |  |     return PL_error(NULL, 0, MSG_ERRNO, ERR_FILE_OPERATION, | 
					
						
							|  |  |  | 		    ATOM_reposition, ATOM_stream, stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->position->byteno  = byteno; | 
					
						
							|  |  |  |   s->position->charno  = charno; | 
					
						
							|  |  |  |   s->position->lineno  = (int)lineno; | 
					
						
							|  |  |  |   s->position->linepos = (int)linepos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   releaseStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("seek", 4, seek, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   atom_t m; | 
					
						
							|  |  |  |   int whence = -1; | 
					
						
							|  |  |  |   int64_t off, new; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   term_t stream = A1; | 
					
						
							|  |  |  |   term_t offset = A2; | 
					
						
							|  |  |  |   term_t method = A3; | 
					
						
							|  |  |  |   term_t newloc = A4; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !(PL_get_atom_ex(method, &m)) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( m == ATOM_bof ) | 
					
						
							|  |  |  |     whence = SIO_SEEK_SET; | 
					
						
							|  |  |  |   else if ( m == ATOM_current ) | 
					
						
							|  |  |  |     whence = SIO_SEEK_CUR; | 
					
						
							|  |  |  |   else if ( m == ATOM_eof ) | 
					
						
							|  |  |  |     whence = SIO_SEEK_END; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return PL_error("seek", 4, NULL, ERR_DOMAIN, ATOM_seek_method, method); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !PL_get_int64(offset, &off) ) | 
					
						
							|  |  |  |     return PL_error("seek", 4, NULL, ERR_DOMAIN, ATOM_integer, offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_stream_handle(stream, &s) ) | 
					
						
							|  |  |  |   { int unit = Sunit_size(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     off *= unit; | 
					
						
							|  |  |  |     if ( Sseek64(s, off, whence) < 0 ) | 
					
						
							|  |  |  |     { if ( errno == EINVAL ) | 
					
						
							|  |  |  | 	PL_error("seek", 4, "offset out of range", ERR_DOMAIN, | 
					
						
							|  |  |  | 		 ATOM_position, offset); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	PL_error("seek", 4, OsError(), ERR_PERMISSION, | 
					
						
							|  |  |  | 		 ATOM_reposition, ATOM_stream, stream); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       Sclearerr(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       releaseStream(s); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new = Stell64(s); | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     new /= unit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PL_unify_int64(newloc, new); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  set_input(+ _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Set stream  _S_ as the current input stream. Predicates like read/1 | 
					
						
							|  |  |  | and get/1 will start using stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_input", 1, set_input, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getInputStream(A1, S_DONTCARE, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurin = s; | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  set_output(+ _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Set stream  _S_ as the current output stream. Predicates like | 
					
						
							|  |  |  | write/1 and put/1 will start using stream  _S_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_output", 1, set_output, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getOutputStream(A1, S_DONTCARE, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Scurout = s; | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  current_input(- _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _S_ with the current input stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("current_input", 1, current_input, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return PL_unify_stream(A1, Scurin); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  current_output(- _S_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _S_ with the current output stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("current_output", 1, current_output, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return PL_unify_stream(A1, Scurout); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  character_count(+ _Stream_,- _ByteCount_)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _CharacterCount_ with the number of bytes written to or | 
					
						
							|  |  |  | read from  _Stream_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("byte_count", 2, byte_count, 0) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( getStreamWithPosition(A1, &s) ) | 
					
						
							|  |  |  |   { int64_t n = s->position->byteno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return PL_unify_int64(A2, n); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  character_count(+ _Stream_,- _CharacterCount_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _CharacterCount_ with the number of characters written to or | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | read from  _Stream_. | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("character_count", 2, character_count, 0) | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( getStreamWithPosition(A1, &s) ) | 
					
						
							|  |  |  |   { int64_t n = s->position->charno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return PL_unify_int64(A2, n); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  line_count(+ _Stream_,- _LineNumber_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _LineNumber_ with the line number for the  _Stream_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("line_count", 2, line_count, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( getStreamWithPosition(A1, &s) ) | 
					
						
							|  |  |  |   { intptr_t n = s->position->lineno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return PL_unify_integer(A2, n); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  line_position(+ _Stream_,- _LinePosition_)
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unify  _LinePosition_ with the position on current text stream | 
					
						
							|  |  |  |  _Stream_. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("line_position", 2, line_position, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( getStreamWithPosition(A1, &s) ) | 
					
						
							|  |  |  |   { intptr_t n = s->position->linepos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseStream(s); | 
					
						
							|  |  |  |     return PL_unify_integer(A2, n); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("source_location", 2, source_location, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( ReadingSource && | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |        PL_unify_atom(A1, source_file_name) && | 
					
						
							|  |  |  |        PL_unify_integer(A2, source_line_no) ) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | at_end_of_stream(term_t stream ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( getInputStream(stream, S_DONTCARE, &s) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int rval = Sfeof(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( rval < 0 ) | 
					
						
							|  |  |  |     { PL_error(NULL, 0, "not-buffered stream", ERR_PERMISSION, | 
					
						
							|  |  |  | 	       ATOM_end_of_stream, ATOM_stream, stream); | 
					
						
							|  |  |  |       rval = FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( rval && Sferror(s) )		/* due to error */ | 
					
						
							|  |  |  |       return streamStatus(s); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       releaseStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rval; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE;				/* exception */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  at_end_of_stream(+ _S_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Succeed if the stream  _S_ has stream position end-of-stream or | 
					
						
							|  |  |  | past-end-of-stream. Note that  _S_ must be a readable stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("at_end_of_stream", 1, at_end_of_stream, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return at_end_of_stream(A1 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  at_end_of_stream is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Succeed if the current stream has stream position end-of-stream or | 
					
						
							|  |  |  | past-end-of-stream. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("at_end_of_stream", 0, at_end_of_stream0, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return at_end_of_stream(0 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static foreign_t | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | peek(term_t stream, term_t chr, int how ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getInputStream(stream, how == PL_BYTE ? S_BINARY : S_TEXT, &s) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2014-09-09 23:53:10 -05:00
										 |  |  |   if ( True(s, SIO_NBUF) || (s->bufsize && s->bufsize < PL_MB_LEN_MAX) ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { releaseStream(s); | 
					
						
							|  |  |  |     return PL_error(NULL, 0, "stream is unbuffered", ERR_PERMISSION, | 
					
						
							|  |  |  | 		    ATOM_peek, ATOM_stream, stream); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   if ( how == PL_BYTE ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { IOPOS pos = s->posbuf; | 
					
						
							|  |  |  |     c = Sgetc(s); | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |     if ( c != EOF ){ | 
					
						
							|  |  |  |        Sungetc(c, s); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     s->posbuf = pos; | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   } else { | 
					
						
							|  |  |  | c = Speekcode(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   if ( Sferror(s) ) | 
					
						
							|  |  |  |     return streamStatus(s); | 
					
						
							|  |  |  |   releaseStream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PL_unify_char(chr, c, how); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-12-24 15:32:29 +00:00
										 |  |  |  * @ingroup CharsIO | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  peek_byte(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is a character code, and  _S_ is a binary | 
					
						
							|  |  |  | stream, read the next byte from the current stream and unify its code | 
					
						
							|  |  |  | with  _C_, while leaving the current stream position unaltered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_byte", 2, peek_byte2, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(A1, A2, PL_BYTE PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  peek_byte(- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is a character code, and the current stream is a | 
					
						
							|  |  |  | binary stream, read the next byte from the current stream and unify its | 
					
						
							|  |  |  | code with  _C_, while leaving the current stream position unaltered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_byte", 1, peek_byte1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(0, A1, PL_BYTE PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  peek_code(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the stream  _S_ is a text stream, read the next character from that | 
					
						
							|  |  |  | stream and unify its representation as an atom with  _C_, while leaving | 
					
						
							|  |  |  | the current stream position unaltered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_code", 2, peek_code2, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(A1, A2, PL_CODE PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred  peek_code(+ _S_,- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the stream  _S_ is a text stream, read the next character from that | 
					
						
							|  |  |  | stream and unify its representation as an atom with  _C_, while leaving | 
					
						
							|  |  |  | the current stream position unaltered. | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_code", 1, peek_code1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(0, A1, PL_CODE PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /** @pred  peek_char(+ _S_,- _C_) is iso
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the stream  _S_ is a text stream, read the next character from that | 
					
						
							|  |  |  | stream and unify its representation as an atom with  _C_, while leaving | 
					
						
							|  |  |  | the current stream position unaltered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_char", 2, peek_char2, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(A1, A2, PL_CHAR PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | /** @pred  peek_char(- _C_) is iso
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If  _C_ is unbound, or is an atom representation of a character, and | 
					
						
							|  |  |  | the current stream is a text stream, read the next character from the | 
					
						
							|  |  |  | current stream and unify its atom representation with  _C_, while | 
					
						
							|  |  |  | leaving the current stream position unaltered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("peek_char", 1, peek_char1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | { PRED_LD | 
					
						
							|  |  |  |   return peek(0, A1, PL_CHAR PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-12-24 15:32:29 +00:00
										 |  |  |  * @ingroup StreamM | 
					
						
							| 
									
										
										
										
											2014-09-15 13:10:49 -05:00
										 |  |  |  * @{ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	    INTERACTION		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | set_prolog_IO(+In, +Out, +Error) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct wrappedIO | 
					
						
							|  |  |  | { void		   *wrapped_handle;	/* original handle */ | 
					
						
							|  |  |  |   IOFUNCTIONS      *wrapped_functions;	/* original functions */ | 
					
						
							|  |  |  |   IOSTREAM	   *wrapped_stream;	/* stream we wrapped */ | 
					
						
							|  |  |  |   IOFUNCTIONS       functions;		/* new function block */ | 
					
						
							|  |  |  | } wrappedIO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | ssize_t | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | Sread_user(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   wrappedIO *wio = handle; | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   ssize_t rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( LD->prompt.next && ttymode != TTY_RAW ) | 
					
						
							|  |  |  |     PL_write_prompt(TRUE); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     Sflush(Suser_output); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   rc = (*wio->wrapped_functions->read)(wio->wrapped_handle, buf, size); | 
					
						
							|  |  |  |   if ( rc == 0 )			/* end-of-file */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Sclearerr(Suser_input); | 
					
						
							|  |  |  |     LD->prompt.next = TRUE; | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   } else if ( rc == 1 && buf[0] == 04 ) | 
					
						
							|  |  |  |   { rc = 0;				/* Map ^D to end-of-file */ | 
					
						
							|  |  |  |   } else if ( rc > 0 && buf[rc-1] == '\n' ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     LD->prompt.next = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   return rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | closeWrappedIO(void *handle) | 
					
						
							|  |  |  | { wrappedIO *wio = handle; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( wio->wrapped_functions->close ) | 
					
						
							|  |  |  |     rval = (*wio->wrapped_functions->close)(wio->wrapped_handle); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     rval = 0; | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   wio->wrapped_stream->functions = wio->wrapped_functions; | 
					
						
							|  |  |  |   wio->wrapped_stream->handle = wio->wrapped_handle; | 
					
						
							|  |  |  |   PL_free(wio); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | wrapIO(IOSTREAM *s, | 
					
						
							|  |  |  |        ssize_t (*read)(void *, char *, size_t), | 
					
						
							|  |  |  |        ssize_t (*write)(void *, char *, size_t)) | 
					
						
							|  |  |  | { wrappedIO *wio = PL_malloc(sizeof(*wio)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   wio->wrapped_functions = s->functions; | 
					
						
							|  |  |  |   wio->wrapped_handle =	s->handle; | 
					
						
							|  |  |  |   wio->wrapped_stream = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   wio->functions = *s->functions; | 
					
						
							|  |  |  |   if ( read  ) wio->functions.read  = read; | 
					
						
							|  |  |  |   if ( write ) wio->functions.write = write; | 
					
						
							|  |  |  |   wio->functions.close = closeWrappedIO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->functions = &wio->functions; | 
					
						
							|  |  |  |   s->handle = wio; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("set_prolog_IO", 3, set_prolog_IO, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   IOSTREAM *in = NULL, *out = NULL, *error = NULL; | 
					
						
							|  |  |  |   int rval = FALSE; | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   int wrapin = FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   if ( !term_stream_handle(A1, &in, SH_ERRORS|SH_ALIAS|SH_UNLOCKED PASS_LD) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   wrapin = (LD->IO.streams[0] != in); | 
					
						
							|  |  |  |   if ( wrapin ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { if ( !(in = getStream(in)) )	/* lock it */ | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   if ( !term_stream_handle(A2, &out, SH_ERRORS|SH_ALIAS PASS_LD) ) | 
					
						
							|  |  |  |     goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( PL_compare(A2, A3) == 0 )	/* == */ | 
					
						
							|  |  |  |   { error = getStream(Snew(out->handle, out->flags, out->functions)); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     if ( !error ) | 
					
						
							|  |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     error->flags &= ~SIO_ABUF;		/* disable buffering */ | 
					
						
							|  |  |  |     error->flags |= SIO_NBUF; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( !PL_get_stream_handle(A3, &error) ) | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK(); | 
					
						
							|  |  |  |   out->flags &= ~SIO_ABUF;		/* output: line buffered */ | 
					
						
							|  |  |  |   out->flags |= SIO_LBUF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LD->IO.streams[1] = out;		/* user_output */ | 
					
						
							|  |  |  |   LD->IO.streams[2] = error;		/* user_error */ | 
					
						
							|  |  |  |   LD->IO.streams[4] = out;		/* current_output */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   if ( wrapin ) | 
					
						
							|  |  |  |   { LD->IO.streams[3] = in;		/* current_input */ | 
					
						
							|  |  |  |     LD->IO.streams[0] = in;		/* user_input */ | 
					
						
							|  |  |  |     wrapIO(in, Sread_user, NULL); | 
					
						
							|  |  |  |     LD->prompt.next = TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   for(i=0; i<3; i++) | 
					
						
							|  |  |  |   { LD->IO.streams[i]->position = &LD->IO.streams[0]->posbuf; | 
					
						
							|  |  |  |     LD->IO.streams[i]->flags |= SIO_RECORDPOS; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   UNLOCK(); | 
					
						
							|  |  |  |   rval = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							| 
									
										
										
										
											2010-02-22 09:35:47 +00:00
										 |  |  |   if ( wrapin && in ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     releaseStream(in); | 
					
						
							|  |  |  |   if ( out ) | 
					
						
							|  |  |  |     releaseStream(out); | 
					
						
							|  |  |  |   if ( error && error != out ) | 
					
						
							|  |  |  |     releaseStream(error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("$size_stream", 2, size_stream, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { GET_LD | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |   if ( !PL_get_stream_handle(A1, &s) ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   rval = PL_unify_int64(A2, Ssize(s)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   PL_release_stream(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | copy_stream_data(+StreamIn, +StreamOut, [Len]) | 
					
						
							|  |  |  | 	Copy all data from StreamIn to StreamOut.  Should be somewhere else, | 
					
						
							|  |  |  | 	and maybe we need something else to copy resources. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | copy_stream_data(term_t in, term_t out, term_t len ARG_LD) | 
					
						
							|  |  |  | { IOSTREAM *i, *o; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int c; | 
					
						
							|  |  |  |   int count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getInputStream(in, S_DONTCARE, &i) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return FALSE; | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   if ( !getOutputStream(out, S_DONTCARE, &o) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { releaseStream(i); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !len ) | 
					
						
							|  |  |  |   { while ( (c = Sgetcode(i)) != EOF ) | 
					
						
							|  |  |  |     { if ( (++count % 4096) == 0 && PL_handle_signals() < 0 ) | 
					
						
							|  |  |  |       { releaseStream(i); | 
					
						
							|  |  |  | 	releaseStream(o); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       if ( Sputcode(c, o) < 0 ) | 
					
						
							|  |  |  |       { releaseStream(i); | 
					
						
							|  |  |  | 	return streamStatus(o); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { int64_t n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !PL_get_int64_ex(len, &n) ) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  |       return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     while ( n-- > 0 && (c = Sgetcode(i)) != EOF ) | 
					
						
							|  |  |  |     { if ( (++count % 4096) == 0 && PL_handle_signals() < 0 ) | 
					
						
							|  |  |  |       { releaseStream(i); | 
					
						
							|  |  |  | 	releaseStream(o); | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	return FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       if ( Sputcode(c, o) < 0 ) | 
					
						
							|  |  |  |       { releaseStream(i); | 
					
						
							|  |  |  | 	return streamStatus(o); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   releaseStream(o); | 
					
						
							|  |  |  |   return streamStatus(i); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred copy_stream_data( +_Source_, +_Output_, +_Len_)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copy at most _Len_ characters from stream _Source_ to stream _Output_. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("copy_stream_data", 3, copy_stream_data3, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   return copy_stream_data(A1, A2, A3 PASS_LD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /** @pred copy_stream_data( +_Source_, +_Output_)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copy all the data left in _Source_ to stream _Output_. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | static | 
					
						
							|  |  |  | PRED_IMPL("copy_stream_data", 2, copy_stream_data2, 0) | 
					
						
							|  |  |  | { PRED_LD | 
					
						
							|  |  |  |   return copy_stream_data(A1, A2, 0 PASS_LD); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 03:13:50 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *      PUBLISH PREDICATES	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BeginPredDefs(file) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 					/* ISO IO */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("open", 4, open4, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("open", 3, open3, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("close", 1, close, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("close", 2, close2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("set_input", 1, set_input, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("set_output", 1, set_output, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("current_input", 1, current_input, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("current_output", 1, current_output, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_code", 2, get_code2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_code", 1, get_code1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_char", 2, get_char2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_char", 1, get_char1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_byte", 2, get_byte2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("get_byte", 1, get_byte1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_code", 2, peek_code2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_code", 1, peek_code1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_char", 2, peek_char2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_char", 1, peek_char1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_byte", 2, peek_byte2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("peek_byte", 1, peek_byte1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_byte", 2, put_byte2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_byte", 1, put_byte1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_code", 2, put_code2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_code", 1, put_code1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_char", 2, put_code2, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("put_char", 1, put_code1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("flush_output", 0, flush_output, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("flush_output", 1, flush_output1, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("at_end_of_stream", 1, at_end_of_stream, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("at_end_of_stream", 0, at_end_of_stream0, PL_FA_ISO) | 
					
						
							|  |  |  |   PRED_DEF("stream_property", 2, stream_property, | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 	   PL_FA_ISO|PL_FA_NONDETERMINISTIC) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("set_stream_position", 2, set_stream_position, PL_FA_ISO) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* edinburgh IO */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("see", 1, see, 0) | 
					
						
							|  |  |  |   PRED_DEF("seen", 0, seen, 0) | 
					
						
							|  |  |  |   PRED_DEF("seeing", 1, seeing, 0) | 
					
						
							|  |  |  |   PRED_DEF("tell", 1, tell, 0) | 
					
						
							|  |  |  |   PRED_DEF("append", 1, append, 0) | 
					
						
							|  |  |  |   PRED_DEF("told", 0, told, 0) | 
					
						
							|  |  |  |   PRED_DEF("telling", 1, telling, 0) | 
					
						
							|  |  |  |   PRED_DEF("put", 2, put2, 0) | 
					
						
							|  |  |  |   PRED_DEF("put", 1, put1, 0) | 
					
						
							|  |  |  |   PRED_DEF("skip", 1, skip1, 0) | 
					
						
							|  |  |  |   PRED_DEF("skip", 2, skip2, 0) | 
					
						
							|  |  |  |   PRED_DEF("get", 1, get1, 0) | 
					
						
							|  |  |  |   PRED_DEF("get", 2, get2, 0) | 
					
						
							|  |  |  |   PRED_DEF("get0", 2, get_code2, 0) | 
					
						
							|  |  |  |   PRED_DEF("get0", 1, get_code1, 0) | 
					
						
							|  |  |  |   PRED_DEF("ttyflush", 0, ttyflush, 0) | 
					
						
							|  |  |  |   PRED_DEF("prompt", 2, prompt, 0) | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | PRED_DEF("tab", 2, tab2, 0) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("tab", 1, tab1, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 					/* Quintus IO */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("byte_count", 2, byte_count, 0) | 
					
						
							|  |  |  |   PRED_DEF("character_count", 2, character_count, 0) | 
					
						
							|  |  |  |   PRED_DEF("line_count", 2, line_count, 0) | 
					
						
							|  |  |  |   PRED_DEF("line_position", 2, line_position, 0) | 
					
						
							|  |  |  |   PRED_DEF("open_null_stream", 1, open_null_stream, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* SWI specific */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("is_stream", 1, is_stream, 0) | 
					
						
							|  |  |  |   PRED_DEF("set_stream", 2, set_stream, 0) | 
					
						
							|  |  |  |   PRED_DEF("with_output_to", 2, with_output_to, PL_FA_TRANSPARENT) | 
					
						
							|  |  |  |   PRED_DEF("set_prolog_IO", 3, set_prolog_IO, 0) | 
					
						
							|  |  |  |   PRED_DEF("protocol", 1, protocol, 0) | 
					
						
							|  |  |  |   PRED_DEF("protocola", 1, protocola, 0) | 
					
						
							|  |  |  |   PRED_DEF("noprotocol", 0, noprotocol, 0) | 
					
						
							|  |  |  |   PRED_DEF("protocolling", 1, protocolling, 0) | 
					
						
							|  |  |  |   PRED_DEF("prompt1", 1, prompt1, 0) | 
					
						
							|  |  |  |   PRED_DEF("seek", 4, seek, 0) | 
					
						
							|  |  |  |   PRED_DEF("wait_for_input", 3, wait_for_input, 0) | 
					
						
							|  |  |  |   PRED_DEF("get_single_char", 1, get_single_char, 0) | 
					
						
							|  |  |  |   PRED_DEF("read_pending_input", 3, read_pending_input, 0) | 
					
						
							|  |  |  |   PRED_DEF("source_location", 2, source_location, 0) | 
					
						
							|  |  |  |   PRED_DEF("copy_stream_data", 3, copy_stream_data3, 0) | 
					
						
							|  |  |  |   PRED_DEF("copy_stream_data", 2, copy_stream_data2, 0) | 
					
						
							|  |  |  |   PRED_DEF("stream_pair", 3, stream_pair, 0) | 
					
						
							|  |  |  |   PRED_DEF("set_end_of_stream", 1, set_end_of_stream, 0) | 
					
						
							| 
									
										
										
										
											2009-06-01 15:39:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* SWI internal */ | 
					
						
							| 
									
										
										
										
											2013-01-16 00:19:07 +00:00
										 |  |  |   PRED_DEF("$push_input_context", 1, push_input_context, 0) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("$pop_input_context", 0, pop_input_context, 0) | 
					
						
							| 
									
										
										
										
											2013-01-15 16:51:55 +00:00
										 |  |  |   PRED_DEF("$input_context", 1, input_context, 0) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   PRED_DEF("$size_stream", 2, size_stream, 0) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | EndPredDefs | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if __YAP_PROLOG__
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-11 23:21:23 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-03-11 20:36:40 +00:00
										 |  |  | pl_get_time(term_t t) | 
					
						
							|  |  |  | { return PL_unify_float(t, WallTime()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-03-11 19:49:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static word | 
					
						
							|  |  |  | pl_sleep(term_t time) | 
					
						
							|  |  |  | { double t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( PL_get_float_ex(time, &t) ) | 
					
						
							|  |  |  |     return Pause(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fail; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | static const PL_extension foreigns[] = { | 
					
						
							|  |  |  |   FRG("nl",			0, pl_nl,			ISO), | 
					
						
							|  |  |  |   FRG("write_canonical",	1, pl_write_canonical,	      ISO), | 
					
						
							|  |  |  |   FRG("write_term",		2, pl_write_term,	      ISO), | 
					
						
							|  |  |  |   FRG("write_term",		3, pl_write_term3,	      ISO), | 
					
						
							|  |  |  |   FRG("write",			1, pl_write,		      ISO), | 
					
						
							|  |  |  |   FRG("writeq",			1, pl_writeq,		      ISO), | 
					
						
							|  |  |  |   FRG("print",			1, pl_print,			0), | 
					
						
							| 
									
										
										
										
											2014-10-05 23:51:43 +01:00
										 |  |  |   FRG("writeln",		1, pl_writeln,			0), | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   FRG("nl",			1, pl_nl1,		      ISO), | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   FRG("format",			2, pl_format,		     METAP), | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   FRG("write",			2, pl_write2,		      ISO), | 
					
						
							|  |  |  |   FRG("writeq",			2, pl_writeq2,		      ISO), | 
					
						
							|  |  |  |   FRG("print",			2, pl_print2,			0), | 
					
						
							|  |  |  |   FRG("write_canonical",	2, pl_write_canonical2,	      ISO), | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   FRG("format",			3, pl_format3,		     METAP), | 
					
						
							| 
									
										
										
										
											2011-03-11 19:49:32 +00:00
										 |  |  |   FRG("sleep",			1, pl_sleep,			0), | 
					
						
							| 
									
										
										
										
											2011-03-11 20:36:40 +00:00
										 |  |  |   FRG("get_time",		1, pl_get_time,			0), | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-09 13:33:30 +00:00
										 |  |  |   // vsc
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   FRG("format_predicate",	2, pl_format_predicate,	     METAP), | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   FRG("current_format_predicate", 2, pl_current_format_predicate, | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 						        METAP|NDET), | 
					
						
							| 
									
										
										
										
											2011-02-23 17:46:50 +00:00
										 |  |  |   FRG("$raw_read",		1, pl_raw_read,			0), | 
					
						
							|  |  |  |   FRG("$raw_read",		2, pl_raw_read2,		0), | 
					
						
							| 
									
										
										
										
											2011-03-26 15:17:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   FRG("$swi_current_prolog_flag",	5, pl_prolog_flag5,	     NDET), | 
					
						
							|  |  |  |   FRG("$swi_current_prolog_flag",	2, pl_prolog_flag,	 NDET|ISO), | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   /* DO NOT ADD ENTRIES BELOW THIS ONE */ | 
					
						
							|  |  |  |   LFRG((char *)NULL,		0, NULL,			0) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-22 17:35:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-03 11:41:21 +00:00
										 |  |  | struct PL_local_data *Yap_InitThreadIO(int wid) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-11 19:49:32 +00:00
										 |  |  |   struct PL_local_data *p; | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   if (wid) | 
					
						
							| 
									
										
										
										
											2011-03-11 19:49:32 +00:00
										 |  |  |     p = (struct PL_local_data *)malloc(sizeof(struct PL_local_data)); | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     return &lds; | 
					
						
							| 
									
										
										
										
											2011-03-03 11:41:21 +00:00
										 |  |  |   if (!p) { | 
					
						
							| 
									
										
										
										
											2015-09-25 10:57:26 +01:00
										 |  |  |     Yap_Error(RESOURCE_ERROR_HEAP, 0L, "Creating thread %d\n", wid); | 
					
						
							| 
									
										
										
										
											2011-03-11 19:49:32 +00:00
										 |  |  |     return p; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-03-11 23:21:23 +00:00
										 |  |  | #if THREADS
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   memcpy(p, Yap_local[0]->PL_local_data_p_, sizeof(struct PL_local_data)); | 
					
						
							| 
									
										
										
										
											2011-03-11 23:21:23 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-03-03 11:41:21 +00:00
										 |  |  |   return p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 12:41:28 +00:00
										 |  |  | #ifdef THREADS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define COUNT_MUTEX_INITIALIZER(name) \
 | 
					
						
							|  |  |  |  { PTHREAD_MUTEX_INITIALIZER, \ | 
					
						
							|  |  |  |    name, \ | 
					
						
							|  |  |  |    0L \ | 
					
						
							|  |  |  |  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | counting_mutex _PL_mutexes[] = | 
					
						
							|  |  |  | { COUNT_MUTEX_INITIALIZER("L_MISC"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_ALLOC"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_ATOM"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_FLAG"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_FUNCTOR"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_RECORD"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_THREAD"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_PREDICATE"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_MODULE"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_TABLE"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_BREAK"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_FILE"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_PLFLAG"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_OP"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_INIT"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_TERM"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_GC"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_AGC"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_STOPTHEWORLD"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_FOREIGN"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_OS"), | 
					
						
							|  |  |  |   COUNT_MUTEX_INITIALIZER("L_LOCALE") | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  | , COUNT_MUTEX_INITIALIZER("L_DDE") | 
					
						
							|  |  |  | , COUNT_MUTEX_INITIALIZER("L_CSTACK") | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | initMutexes( void ) | 
					
						
							|  |  |  | { counting_mutex *m; | 
					
						
							|  |  |  |   int n = sizeof(_PL_mutexes)/sizeof(*m); | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(i=0, m=_PL_mutexes; i<n; i++, m++) | 
					
						
							|  |  |  |     simpleMutexInit(&m->mutex); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | init_yap(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-03 11:41:21 +00:00
										 |  |  |   GET_LD | 
					
						
							| 
									
										
										
										
											2013-10-29 12:41:28 +00:00
										 |  |  | #ifdef THREADS
 | 
					
						
							|  |  |  |   initMutexes(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-03-26 15:17:17 +00:00
										 |  |  |   /* we need encodings first */ | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   initLocale(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   initCharTypes(); | 
					
						
							| 
									
										
										
										
											2014-10-07 01:37:13 +01:00
										 |  |  |   debugstatus.styleCheck = LONGATOM_CHECK|MULTITON_CHECK|DISCONTIGUOUS_STYLE|MULTIPLE_CHECK|SINGLETON_CHECK; | 
					
						
							| 
									
										
										
										
											2011-03-26 15:17:17 +00:00
										 |  |  |   initPrologFlags(); | 
					
						
							| 
									
										
										
										
											2013-12-13 08:42:57 +00:00
										 |  |  |   clearPrologFlagMask(PLFLAG_DEBUGINFO); | 
					
						
							| 
									
										
										
										
											2011-03-26 15:17:17 +00:00
										 |  |  |   setPrologFlagMask(PLFLAG_TTY_CONTROL); | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   initFiles(); | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_ctype); | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_file); | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_files); | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_glob); | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_write); | 
					
						
							| 
									
										
										
										
											2011-02-12 18:42:44 +00:00
										 |  |  |   PL_register_extensions(PL_predicates_from_read); | 
					
						
							| 
									
										
										
										
											2011-03-09 13:05:03 +00:00
										 |  |  |   PL_register_extensions(PL_predicates_from_tai); | 
					
						
							| 
									
										
										
										
											2011-03-26 15:17:17 +00:00
										 |  |  |   PL_register_extensions(PL_predicates_from_prologflag); | 
					
						
							| 
									
										
										
										
											2014-03-06 02:09:48 +00:00
										 |  |  |   //PL_register_extensions(PL_predicates_from_system);
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_locale); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-06-08 06:55:23 -05:00
										 |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   PL_register_extensions(PL_predicates_from_win); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  |   PL_register_extensions(foreigns); | 
					
						
							|  |  |  |   fileerrors = TRUE; | 
					
						
							|  |  |  |   SinitStreams(); | 
					
						
							| 
									
										
										
										
											2011-02-14 06:49:48 -08:00
										 |  |  |   initOs(); | 
					
						
							| 
									
										
										
										
											2011-02-16 00:23:58 +00:00
										 |  |  |   PL_install_readline(); | 
					
						
							| 
									
										
										
										
											2011-02-10 21:14:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-11 14:06:57 -05:00
										 |  |  | /**
 | 
					
						
							|  |  |  | @} | 
					
						
							|  |  |  | */ |