| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | /*  Part of SWI-Prolog
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Author:        Jan Wielemaker | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     E-mail:        J.Wielemaker@vu.nl | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     WWW:           http://www.swi-prolog.org
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +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-16 11:28:58 +00:00
										 |  |  |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 18:25:33 +00:00
										 |  |  | #if defined(__WINDOWS__) || defined(__MINGW32__)
 | 
					
						
							| 
									
										
										
										
											2014-10-30 07:46:17 +00:00
										 |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #include "windows/uxnt.h"
 | 
					
						
							| 
									
										
										
										
											2013-01-19 11:47:14 +00:00
										 |  |  | #ifdef _YAP_NOT_INSTALLED_
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef WIN64
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #include "config/win64.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #include "config/win32.h"
 | 
					
						
							| 
									
										
										
										
											2011-03-08 00:03:50 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-01-19 11:47:14 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #include <winsock2.h>
 | 
					
						
							|  |  |  | #define CRLF_MAPPING 1
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-11-28 02:34:26 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 01:49:03 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  | #include <android/asset_manager.h>
 | 
					
						
							|  |  |  | #include <android/asset_manager_jni.h>
 | 
					
						
							|  |  |  | #include <android/log.h>
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | int Yap_isAsset( const char *path ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LOG(...) __android_log_print(ANDROID_LOG_DEBUG,"YAP Stream", __VA_ARGS__)
 | 
					
						
							| 
									
										
										
										
											2014-06-12 01:49:03 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-06-14 10:27:39 +01:00
										 |  |  | #define __android_log_print(i,loc,msg,...)
 | 
					
						
							| 
									
										
										
										
											2014-06-12 01:49:03 +01:00
										 |  |  | #define ANDROID_LOG_INFO 0
 | 
					
						
							|  |  |  | #define ANDROID_LOG_ERROR 0
 | 
					
						
							|  |  |  | #define ANDROID_LOG_DEBUG 0
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | #define LOG(...)
 | 
					
						
							| 
									
										
										
										
											2014-06-12 01:49:03 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | This modules defines the  SWI-Prolog  I/O   streams.  These  streams are | 
					
						
							|  |  |  | provided to gain common access to  any   type  of character data: files, | 
					
						
							|  |  |  | stdio streams, but also resources, strings, XPCE objects, etc. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MT: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Multithreading is supported through  Slock()   and  Sunlock(). These are | 
					
						
							|  |  |  | recursive locks. If a stream handle  might   be  known to another thread | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | locking is required. | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if _FILE_OFFSET_BITS == 64 || defined(_LARGE_FILES)
 | 
					
						
							|  |  |  | #define O_LARGEFILES 1		/* use for conditional code in Prolog */
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #undef O_LARGEFILES
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PL_KERNEL 1
 | 
					
						
							| 
									
										
										
										
											2014-03-15 22:29:04 +00:00
										 |  |  | #if HAVE_LOCALE_H && HAVE_SETLOCALE
 | 
					
						
							| 
									
										
										
										
											2014-10-19 03:51:56 +01:00
										 |  |  | //#define O_LOCALE 1
 | 
					
						
							| 
									
										
										
										
											2014-03-15 22:29:04 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #include <wchar.h>
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #define NEEDS_SWINSOCK
 | 
					
						
							| 
									
										
										
										
											2009-06-01 15:55:31 -05:00
										 |  |  | #include "SWI-Stream.h"
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #include "SWI-Prolog.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #include "pl-utf8.h"
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_TIME_H
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #include <time.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #ifdef HAVE_MALLOC_H
 | 
					
						
							|  |  |  | #include <malloc.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_MALLOC_H
 | 
					
						
							|  |  |  | #include <sys/malloc.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include <memory.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <limits.h>
 | 
					
						
							|  |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #ifdef HAVE_SYS_SELECT_H
 | 
					
						
							|  |  |  | #include <sys/select.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_UNISTD_H
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include <stdio.h>			/* sprintf() for numeric values */
 | 
					
						
							|  |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | #ifdef SYSLIB_H
 | 
					
						
							|  |  |  | #include SYSLIB_H
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-19 01:44:11 +01:00
										 |  |  | #if THREADS
 | 
					
						
							|  |  |  | #define O_PLMT 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #define ROUND(p, n) ((((p) + (n) - 1) & ~((n) - 1)))
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #define UNDO_SIZE ROUND(PL_MB_LEN_MAX, sizeof(wchar_t))
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef FALSE
 | 
					
						
							|  |  |  | #define FALSE 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef TRUE
 | 
					
						
							|  |  |  | #define TRUE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define char_to_int(c)	(0xff & (int)(c))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TMPBUFSIZE 256			/* Serror bufsize for Svfprintf() */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Slinesize = SIO_LINESIZE;		/* Sgets() buffer size */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t	S__flushbuf(IOSTREAM *s); | 
					
						
							|  |  |  | static void	run_close_hooks(IOSTREAM *s); | 
					
						
							|  |  |  | static int	S__removebuf(IOSTREAM *s); | 
					
						
							|  |  |  | static int	S__seterror(IOSTREAM *s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  | #define SLOCK(s)    if ( s->mutex ) recursiveMutexLock(s->mutex)
 | 
					
						
							|  |  |  | #define SUNLOCK(s)  if ( s->mutex ) recursiveMutexUnlock(s->mutex)
 | 
					
						
							| 
									
										
										
										
											2014-11-25 19:52:51 +00:00
										 |  |  | static inline int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | STRYLOCK(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->mutex && | 
					
						
							|  |  |  |        recursiveMutexTryLock(s->mutex) == EBUSY ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define SLOCK(s)
 | 
					
						
							|  |  |  | #define SUNLOCK(s)
 | 
					
						
							|  |  |  | #define STRYLOCK(s) (TRUE)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | #include "pl-error.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  | #include "pl-locale.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | extern int			fatalError(const char *fm, ...); | 
					
						
							| 
									
										
										
										
											2013-11-16 16:58:07 +00:00
										 |  |  | extern int			PL_handle_signals( void ); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | extern IOENC			initEncoding(void); | 
					
						
							|  |  |  | extern int			reportStreamError(IOSTREAM *s); | 
					
						
							|  |  |  | extern record_t			PL_record(term_t t); | 
					
						
							|  |  |  | extern int			PL_thread_self(void); | 
					
						
							| 
									
										
										
										
											2014-01-19 21:15:05 +00:00
										 |  |  | extern void			unallocStream(IOSTREAM *s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      BUFFER		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Note that the  buffer  is  allocated   from  s->unbuffer,  which  starts | 
					
						
							|  |  |  | UNDO_SIZE before s->buffer, so we can always push-back a wide | 
					
						
							|  |  |  | character into a multibyte stream. We do not do this for SIO_USERBUF | 
					
						
							|  |  |  | case, but this is only used by the output stream Svfprintf() where it is | 
					
						
							|  |  |  | not needed. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static size_t | 
					
						
							|  |  |  | S__setbuf(IOSTREAM *s, char *buffer, size_t size) | 
					
						
							|  |  |  | { char *newbuf, *newunbuf; | 
					
						
							|  |  |  |   int newflags = s->flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( size == 0 ) | 
					
						
							|  |  |  |     size = SIO_BUFSIZE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_OUTPUT) ) | 
					
						
							|  |  |  |   { if ( S__removebuf(s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( buffer ) | 
					
						
							|  |  |  |   { newunbuf = newbuf = buffer; | 
					
						
							|  |  |  |     newflags |= SIO_USERBUF; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( !(newunbuf = malloc(size+UNDO_SIZE)) ) | 
					
						
							|  |  |  |     { errno = ENOMEM; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     newflags &= ~SIO_USERBUF; | 
					
						
							|  |  |  |     newbuf = newunbuf + UNDO_SIZE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_INPUT) ) | 
					
						
							|  |  |  |   { size_t buffered = s->limitp - s->bufp; | 
					
						
							|  |  |  |     size_t copy = (buffered < size ? buffered : size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( size < buffered ) | 
					
						
							|  |  |  |     { size_t offset = size - buffered; | 
					
						
							|  |  |  |       int64_t newpos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( s->functions->seek64 ) | 
					
						
							|  |  |  |       { newpos = (*s->functions->seek64)(s->handle, offset, SIO_SEEK_CUR); | 
					
						
							|  |  |  |       } else if ( s->functions->seek ) | 
					
						
							|  |  |  |       { newpos = (*s->functions->seek)(s->handle, (long)offset, SIO_SEEK_CUR); | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { newpos = -1; | 
					
						
							|  |  |  | 	errno = ESPIPE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( newpos == -1 ) | 
					
						
							|  |  |  |       { if ( !(newflags & SIO_USERBUF) ) | 
					
						
							|  |  |  | 	{ int oldeno = errno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  free(newunbuf); | 
					
						
							|  |  |  | 	  errno = oldeno; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 	  S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memcpy(newbuf, s->bufp, copy); | 
					
						
							|  |  |  |     S__removebuf(s); | 
					
						
							|  |  |  |     s->unbuffer = newunbuf; | 
					
						
							|  |  |  |     s->bufp = s->buffer = newbuf; | 
					
						
							|  |  |  |     s->limitp = s->buffer+copy; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { s->unbuffer = newunbuf; | 
					
						
							|  |  |  |     s->bufp = s->buffer = newbuf; | 
					
						
							|  |  |  |     s->limitp = &s->buffer[size]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   s->bufsize = (int)size; | 
					
						
							|  |  |  |   s->flags = newflags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Ssetbuffer(IOSTREAM *s, char *buffer, size_t size) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | { if ( S__setbuf(s, buffer, size) != (size_t)-1 ) | 
					
						
							|  |  |  |     s->flags &= ~SIO_USERBUF; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | S__removebuf(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->buffer && s->unbuffer ) | 
					
						
							|  |  |  |   { int rval = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (s->flags & SIO_OUTPUT) && S__flushbuf(s) < 0 ) | 
					
						
							|  |  |  |       rval = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !(s->flags & SIO_USERBUF) ) | 
					
						
							|  |  |  |       free(s->unbuffer); | 
					
						
							|  |  |  |     s->bufp = s->limitp = s->buffer = s->unbuffer = NULL; | 
					
						
							|  |  |  |     s->bufsize = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rval; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-19 01:44:11 +01:00
										 |  |  | #ifdef DEBUGX
 | 
					
						
							|  |  |  | #define DEBUG_IO_LOCKS 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef DEBUG_IO_LOCKS
 | 
					
						
							|  |  |  | static char * | 
					
						
							|  |  |  | Sname(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s == Serror ) return "error"; | 
					
						
							|  |  |  |   if ( s == Sinput ) return "input"; | 
					
						
							|  |  |  |   if ( s == Soutput ) return "output"; | 
					
						
							|  |  |  |   return "?"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <execinfo.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | print_trace(void) | 
					
						
							|  |  |  | { void *array[7]; | 
					
						
							|  |  |  |   size_t size; | 
					
						
							|  |  |  |   char **strings; | 
					
						
							|  |  |  |   size_t i; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   size = backtrace(array, sizeof(array)/sizeof(void *)); | 
					
						
							|  |  |  |   strings = backtrace_symbols(array, size); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   printf(" Stack:"); | 
					
						
							|  |  |  |   for(i = 1; i < size; i++) | 
					
						
							|  |  |  |   { printf("\n\t[%ld] %s", (long)i, strings[i]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   printf("\n"); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   free(strings); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /*DEBUG_IO_LOCKS*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Slock(IOSTREAM *s) | 
					
						
							|  |  |  | { SLOCK(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s->erased ) | 
					
						
							|  |  |  |   { SUNLOCK(s); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef DEBUG_IO_LOCKS
 | 
					
						
							| 
									
										
										
										
											2014-10-19 01:44:11 +01:00
										 |  |  |   if ( DEBUG || s->locks > 2 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { printf("  Lock [%d]: %s: %d locks", PL_thread_self(), Sname(s), s->locks+1); | 
					
						
							|  |  |  |     print_trace(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !s->locks++ ) | 
					
						
							|  |  |  |   { if ( (s->flags & (SIO_NBUF|SIO_OUTPUT)) == (SIO_NBUF|SIO_OUTPUT) ) | 
					
						
							|  |  |  |       return S__setbuf(s, NULL, TMPBUFSIZE) == (size_t)-1 ? -1 : 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | StryLock(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( !STRYLOCK(s) ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s->erased ) | 
					
						
							|  |  |  |   { SUNLOCK(s); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( !s->locks++ ) | 
					
						
							|  |  |  |   { if ( (s->flags & (SIO_NBUF|SIO_OUTPUT)) == (SIO_NBUF|SIO_OUTPUT) ) | 
					
						
							|  |  |  |       return S__setbuf(s, NULL, TMPBUFSIZE) == (size_t)-1 ? -1 : 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | int | 
					
						
							|  |  |  | Sunlock(IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { int rval = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG_IO_LOCKS
 | 
					
						
							|  |  |  |   if ( s->locks > 3 ) | 
					
						
							|  |  |  |   { printf("Unlock [%d]: %s: %d locks", PL_thread_self(), Sname(s), s->locks-1); | 
					
						
							|  |  |  |     print_trace(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->locks ) | 
					
						
							|  |  |  |   { if ( --s->locks == 0 ) | 
					
						
							|  |  |  |     { if ( (s->flags & (SIO_NBUF|SIO_OUTPUT)) == (SIO_NBUF|SIO_OUTPUT) ) | 
					
						
							|  |  |  | 	rval = S__removebuf(s); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { assert(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SUNLOCK(s); | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *		TIMEOUT		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_SELECT
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __WINDOWS__
 | 
					
						
							|  |  |  | typedef int SOCKET; | 
					
						
							|  |  |  | #define INVALID_SOCKET -1
 | 
					
						
							|  |  |  | #define Swinsock(s) Sfileno(s)
 | 
					
						
							|  |  |  | #define NFDS(n) (n+1)
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define NFDS(n) (0)			/* 1st arg of select is ignored */
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | S__wait(IOSTREAM *s) | 
					
						
							|  |  |  | { SOCKET fd = Swinsock(s); | 
					
						
							|  |  |  |   fd_set wait; | 
					
						
							|  |  |  |   struct timeval time; | 
					
						
							|  |  |  |   int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( fd == INVALID_SOCKET ) | 
					
						
							|  |  |  |   { errno = EPERM;			/* no permission to select */ | 
					
						
							|  |  |  |     s->flags |= SIO_FERR; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   time.tv_sec  = s->timeout / 1000; | 
					
						
							|  |  |  |   time.tv_usec = (s->timeout % 1000) * 1000; | 
					
						
							|  |  |  |   FD_ZERO(&wait); | 
					
						
							|  |  |  |   FD_SET(fd, &wait); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { if ( (s->flags & SIO_INPUT) ) | 
					
						
							|  |  |  |       rc = select(NFDS(fd), &wait, NULL, NULL, &time); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       rc = select(NFDS(fd), NULL, &wait, NULL, &time); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( rc < 0 && errno == EINTR ) | 
					
						
							|  |  |  |     { if ( PL_handle_signals() < 0 ) | 
					
						
							|  |  |  |       { errno = EPLEXCEPTION; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( rc == 0 ) | 
					
						
							|  |  |  |   { s->flags |= (SIO_TIMEOUT|SIO_FERR); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0;				/* ok, data available */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /*HAVE_SELECT*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	     FLUSH/FILL		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* return values: -1: error, else #bytes written */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static ssize_t | 
					
						
							|  |  |  | S__flushbuf(IOSTREAM *s) | 
					
						
							|  |  |  | { char *from, *to; | 
					
						
							|  |  |  |   ssize_t rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SLOCK(s); | 
					
						
							|  |  |  |   from = s->buffer; | 
					
						
							|  |  |  |   to   = s->bufp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ( from < to ) | 
					
						
							|  |  |  |   { size_t size = (size_t)(to - from); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     ssize_t n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_SELECT
 | 
					
						
							|  |  |  |     s->flags &= ~SIO_TIMEOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( s->timeout >= 0 ) | 
					
						
							|  |  |  |     { if ( (rc=S__wait(s)) < 0 ) | 
					
						
							|  |  |  | 	goto partial; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n = (*s->functions->write)(s->handle, from, size); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( n > 0 )			/* wrote some */ | 
					
						
							|  |  |  |     { from += n; | 
					
						
							|  |  |  |     } else if ( n < 0 )			/* error */ | 
					
						
							|  |  |  |     { S__seterror(s); | 
					
						
							|  |  |  |       rc = -1; | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |     } else				/* wrote nothing? */ | 
					
						
							|  |  |  |     { break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #ifdef HAVE_SELECT
 | 
					
						
							|  |  |  | partial: | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( to == from )			/* full flush */ | 
					
						
							|  |  |  |   { rc = s->bufp - s->buffer; | 
					
						
							|  |  |  |     s->bufp = s->buffer; | 
					
						
							|  |  |  |   } else				/* partial flush */ | 
					
						
							|  |  |  |   { size_t left = to - from; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rc = from - s->buffer; | 
					
						
							|  |  |  |     memmove(s->buffer, from, left); | 
					
						
							|  |  |  |     s->bufp = s->buffer + left; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |   SUNLOCK(s); | 
					
						
							|  |  |  |   return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | S__flushbufc(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->buffer ) | 
					
						
							|  |  |  |   { if ( S__flushbuf(s) <= 0 )		/* == 0: no progress!? */ | 
					
						
							|  |  |  |       c = -1; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       *s->bufp++ = (c & 0xff); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( s->flags & SIO_NBUF ) | 
					
						
							|  |  |  |     { char chr = (char)c; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( (*s->functions->write)(s->handle, &chr, 1) != 1 ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |       { S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	c = -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { if ( S__setbuf(s, NULL, 0) == (size_t)-1 ) | 
					
						
							|  |  |  | 	c = -1; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	*s->bufp++ = (char)c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | S__fillbuf() fills the read-buffer, returning the first character of it. | 
					
						
							|  |  |  | It also realises the SWI-Prolog timeout facility. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | S__fillbuf(IOSTREAM *s) | 
					
						
							|  |  |  | { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( s->flags & (SIO_FEOF|SIO_FERR) )	/* reading past eof */ | 
					
						
							|  |  |  |   { if ( s->flags & SIO_FEOF2ERR ) | 
					
						
							|  |  |  |       s->flags |= (SIO_FEOF2|SIO_FERR); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       s->flags |= SIO_FEOF2; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_SELECT
 | 
					
						
							|  |  |  |   s->flags &= ~SIO_TIMEOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s->timeout >= 0 && !s->downstream ) | 
					
						
							|  |  |  |   { int rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     if ( (rc=S__wait(s)) < 0 ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       return rc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_NBUF ) | 
					
						
							|  |  |  |   { char chr; | 
					
						
							|  |  |  |     ssize_t n; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     n = (*s->functions->read)(s->handle, &chr, 1); | 
					
						
							|  |  |  |     if ( n == 1 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { c = char_to_int(chr); | 
					
						
							|  |  |  |       return c; | 
					
						
							|  |  |  |     } else if ( n == 0 ) | 
					
						
							|  |  |  |     { if ( !(s->flags & SIO_NOFEOF) ) | 
					
						
							|  |  |  | 	s->flags |= SIO_FEOF; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { S__seterror(s); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { ssize_t n; | 
					
						
							|  |  |  |     size_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !s->buffer ) | 
					
						
							|  |  |  |     { if ( S__setbuf(s, NULL, 0) == (size_t)-1 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       s->bufp = s->limitp = s->buffer; | 
					
						
							|  |  |  |       len = s->bufsize; | 
					
						
							|  |  |  |     } else if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |     { len = s->limitp - s->bufp; | 
					
						
							|  |  |  |       memmove(s->buffer, s->bufp, s->limitp - s->bufp); | 
					
						
							|  |  |  |       s->bufp = s->buffer; | 
					
						
							|  |  |  |       s->limitp = &s->bufp[len]; | 
					
						
							|  |  |  |       len = s->bufsize - len; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { s->bufp = s->limitp = s->buffer; | 
					
						
							|  |  |  |       len = s->bufsize; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  |   n = (*s->functions->read)(s->handle, s->limitp, len); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     if ( n > 0 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { s->limitp += n; | 
					
						
							|  |  |  |       c = char_to_int(*s->bufp++); | 
					
						
							|  |  |  |       return c; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { if ( n == 0 ) | 
					
						
							|  |  |  |       { if ( !(s->flags & SIO_NOFEOF) ) | 
					
						
							|  |  |  | 	  s->flags |= SIO_FEOF; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | #ifdef EWOULDBLOCK
 | 
					
						
							|  |  |  |       } else if ( errno == EWOULDBLOCK ) | 
					
						
							|  |  |  |       { s->bufp = s->buffer; | 
					
						
							|  |  |  | 	s->limitp = s->buffer; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 	S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { S__seterror(s); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	   CHARACTER I/O	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | update_linepos(IOSTREAM *s, int c) | 
					
						
							|  |  |  | { IOPOS *p = s->position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( c > '\r' )			/* speedup the 99% case a bit */ | 
					
						
							|  |  |  |   { p->linepos++; | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(c) | 
					
						
							|  |  |  |   { case '\n': | 
					
						
							|  |  |  |       p->lineno++; | 
					
						
							|  |  |  |       p->linepos = 0; | 
					
						
							|  |  |  |       s->flags &= ~SIO_NOLINEPOS; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case '\r': | 
					
						
							|  |  |  |       p->linepos = 0; | 
					
						
							|  |  |  |       s->flags &= ~SIO_NOLINEPOS; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case '\b': | 
					
						
							|  |  |  |       if ( p->linepos > 0 ) | 
					
						
							|  |  |  | 	p->linepos--; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case EOF: | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case '\t': | 
					
						
							|  |  |  |       p->linepos |= 7; | 
					
						
							| 
									
										
										
										
											2014-03-13 12:54:06 +00:00
										 |  |  |       /*FALLTHROUGH*/ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |       p->linepos++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | S__fcheckpasteeof(IOSTREAM *s, int c) | 
					
						
							|  |  |  | { S__checkpasteeof(s, c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | S__fupdatefilepos_getc(IOSTREAM *s, int c) | 
					
						
							|  |  |  | { IOPOS *p = s->position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   update_linepos(s, c); | 
					
						
							|  |  |  |   p->byteno++; | 
					
						
							|  |  |  |   p->charno++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | S__updatefilepos(IOSTREAM *s, int c) | 
					
						
							|  |  |  | { IOPOS *p = s->position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( p ) | 
					
						
							|  |  |  |   { update_linepos(s, c); | 
					
						
							|  |  |  |     p->charno++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   S__checkpasteeof(s,c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | get_byte(IOSTREAM *s) | 
					
						
							|  |  |  | { int c = Snpgetc(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->position ) | 
					
						
							|  |  |  |     s->position->byteno++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | put_byte(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { c &= 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |   { *s->bufp++ = c; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { if ( S__flushbufc(c, s) < 0 ) | 
					
						
							|  |  |  |     { s->lastc = EOF; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->position ) | 
					
						
							|  |  |  |     s->position->byteno++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sputc(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { c &= 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( put_byte(c, s) < 0 ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->lastc = c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( c == '\n' && (s->flags & SIO_LBUF) ) | 
					
						
							|  |  |  |   { if ( S__flushbuf(s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return S__updatefilepos(s, c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfgetc(IOSTREAM *s) | 
					
						
							|  |  |  | { return Sgetc(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | unget_byte(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { IOPOS *p = s->position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *--s->bufp = c; | 
					
						
							|  |  |  |   if ( p ) | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  |   { p->charno--;			/* sz */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     p->byteno--; | 
					
						
							|  |  |  |     if ( c == '\n' ) | 
					
						
							|  |  |  |       p->lineno--; | 
					
						
							|  |  |  |     s->flags |= SIO_NOLINEPOS; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sungetc(int c, IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   if ( s->bufp > s->unbuffer ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { unget_byte(c, s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return c; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | reperror(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { if ( c >= 0 && (s->flags & (SIO_REPXML|SIO_REPPL)) ) | 
					
						
							|  |  |  |   { char buf[16]; | 
					
						
							|  |  |  |     const char *q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (s->flags & SIO_REPPL) ) | 
					
						
							|  |  |  |     { if ( c <= 0xffff ) | 
					
						
							|  |  |  | 	sprintf(buf, "\\u%04X", c); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	sprintf(buf, "\\U%08X", c); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       sprintf(buf, "&#%d;", c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(q = buf; *q; q++) | 
					
						
							|  |  |  |     { if ( put_byte(*q, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return c; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Sseterr(s, SIO_FERR|SIO_CLEARERR, "Encoding cannot represent character"); | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-11 19:33:18 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  | //hack!!!!
 | 
					
						
							|  |  |  |    char *Yap_AndroidBufp = NULL; | 
					
						
							|  |  |  |    void( *Yap_DisplayWithJava)(int c); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | put_code(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { switch(s->encoding) | 
					
						
							|  |  |  |   { case ENC_OCTET: | 
					
						
							|  |  |  |     case ENC_ISO_LATIN_1: | 
					
						
							|  |  |  |       if ( c >= 256 ) | 
					
						
							|  |  |  |       { if ( reperror(c, s) < 0 ) | 
					
						
							|  |  |  | 	  return -1; | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     simple: | 
					
						
							|  |  |  |       if ( put_byte(c, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case ENC_ASCII: | 
					
						
							|  |  |  |       if ( c >= 128 ) | 
					
						
							|  |  |  |       { if ( reperror(c, s) < 0 ) | 
					
						
							|  |  |  | 	  return -1; | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       goto simple; | 
					
						
							|  |  |  |     case ENC_ANSI: | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     { char b[PL_MB_LEN_MAX]; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       size_t n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( !s->mbstate ) | 
					
						
							|  |  |  |       { if ( !(s->mbstate = malloc(sizeof(*s->mbstate))) ) | 
					
						
							|  |  |  | 	  return EOF;			/* out of memory */ | 
					
						
							|  |  |  | 	memset(s->mbstate, 0, sizeof(*s->mbstate)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( (n = wcrtomb(b, (wchar_t)c, s->mbstate)) == (size_t)-1 ) | 
					
						
							|  |  |  |       { if ( reperror(c, s) < 0 ) | 
					
						
							|  |  |  | 	  return -1; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0; i<n; i++) | 
					
						
							|  |  |  | 	{ if ( put_byte(b[i]&0xff, s) < 0 ) | 
					
						
							|  |  |  | 	    return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_UTF8: | 
					
						
							|  |  |  |     { char buf[6]; | 
					
						
							|  |  |  |       char *p, *end; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( c < 128 ) | 
					
						
							|  |  |  | 	goto simple; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       end = utf8_put_char(buf, c); | 
					
						
							|  |  |  |       for(p=buf; p<end; p++) | 
					
						
							|  |  |  |       { if ( put_byte(*p&0xff, s) < 0 ) | 
					
						
							|  |  |  | 	  return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_UNICODE_BE: | 
					
						
							|  |  |  |       if ( put_byte(c>>8, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       if ( put_byte(c&0xff, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case ENC_UNICODE_LE: | 
					
						
							|  |  |  |       if ( put_byte(c&0xff, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       if ( put_byte(c>>8, s) < 0 ) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case ENC_WCHAR: | 
					
						
							|  |  |  |     { pl_wchar_t chr = c; | 
					
						
							|  |  |  |       unsigned char *q = (unsigned char *)&chr; | 
					
						
							|  |  |  |       unsigned char *e = &q[sizeof(pl_wchar_t)]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-04 01:27:58 +00:00
										 |  |  | #if __WINDOWS__
 | 
					
						
							|  |  |  |   if (s == Soutput || s == Serror ) { | 
					
						
							|  |  |  |     if (!(*s->functions->write)(s->handle, (char *)q, sizeof(wchar_t))) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       while(q<e) | 
					
						
							|  |  |  |       { if ( put_byte(*q++, s) < 0 ) | 
					
						
							|  |  |  | 	  return -1; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_UNKNOWN: | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->lastc = c; | 
					
						
							| 
									
										
										
										
											2014-06-11 19:33:18 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-11 19:33:18 +01:00
										 |  |  |   if (Yap_AndroidBufp && (s == Soutput || s == Serror) ) { | 
					
						
							|  |  |  |      (Yap_DisplayWithJava)(c); | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (c == '\n' && (s->flags & SIO_LBUF) ) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { if ( S__flushbuf(s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return S__updatefilepos(s, c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sputcode(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { if ( c < 0 ) | 
					
						
							|  |  |  |     return reperror(c, s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->tee && s->tee->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |     Sputcode(c, s->tee); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( c == '\n' && | 
					
						
							|  |  |  |        (s->flags&SIO_TEXT) && | 
					
						
							|  |  |  |        s->newline == SIO_NL_DOS && | 
					
						
							|  |  |  |        s->lastc != '\r' ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { if ( put_code('\r', s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return put_code(c, s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Scanrepresent(int c, IOSTREAM *s) | 
					
						
							|  |  |  | { switch(s->encoding) | 
					
						
							|  |  |  |   { case ENC_OCTET: | 
					
						
							|  |  |  |     case ENC_ISO_LATIN_1: | 
					
						
							|  |  |  |       if ( c <= 0xff ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     case ENC_ASCII: | 
					
						
							|  |  |  |       if ( c < 0x7f ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     case ENC_ANSI: | 
					
						
							|  |  |  |     { mbstate_t state; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       char b[PL_MB_LEN_MAX]; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       memset(&state, 0, sizeof(state)); | 
					
						
							|  |  |  |       if ( wcrtomb(b, (wchar_t)c, &state) != (size_t)-1 ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_WCHAR: | 
					
						
							|  |  |  |       if ( sizeof(wchar_t) > 2 ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |     /*FALLTHROUGH*/ | 
					
						
							|  |  |  |     case ENC_UNICODE_BE: | 
					
						
							|  |  |  |     case ENC_UNICODE_LE: | 
					
						
							|  |  |  |       if ( c <= 0xffff ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     case ENC_UTF8: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       assert(0); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sgetcode(IOSTREAM *s) | 
					
						
							|  |  |  | { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | retry: | 
					
						
							|  |  |  |   switch(s->encoding) | 
					
						
							|  |  |  |   { case ENC_OCTET: | 
					
						
							|  |  |  |     case ENC_ISO_LATIN_1: | 
					
						
							|  |  |  |       c = get_byte(s); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case ENC_ASCII: | 
					
						
							|  |  |  |     { c = get_byte(s); | 
					
						
							|  |  |  |       if ( c > 128 ) | 
					
						
							|  |  |  | 	Sseterr(s, SIO_WARN, "non-ASCII character"); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_ANSI: | 
					
						
							|  |  |  |     { char b[1]; | 
					
						
							|  |  |  |       size_t rc, n = 0; | 
					
						
							|  |  |  |       wchar_t wc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( !s->mbstate ) | 
					
						
							|  |  |  |       { if ( !(s->mbstate = malloc(sizeof(*s->mbstate))) ) | 
					
						
							|  |  |  | 	  return EOF;			/* out of memory */ | 
					
						
							|  |  |  | 	memset(s->mbstate, 0, sizeof(*s->mbstate)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(;;) | 
					
						
							|  |  |  |       { if ( (c = get_byte(s)) == EOF ) | 
					
						
							|  |  |  | 	{ if ( n == 0 ) | 
					
						
							|  |  |  | 	  { goto out; | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	  { Sseterr(s, SIO_WARN, "EOF in multibyte Sequence"); | 
					
						
							|  |  |  | 	    goto mberr; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	b[0] = c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( (rc=mbrtowc(&wc, b, 1, s->mbstate)) == 1 ) | 
					
						
							|  |  |  | 	{ c = wc; | 
					
						
							|  |  |  | 	  goto out; | 
					
						
							|  |  |  | 	} else if ( rc == (size_t)-1 ) | 
					
						
							|  |  |  | 	{ Sseterr(s, SIO_WARN, "Illegal multibyte Sequence"); | 
					
						
							|  |  |  | 	  goto mberr; | 
					
						
							|  |  |  | 	}				/* else -2: incomplete */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mberr: | 
					
						
							|  |  |  |       c = UTF8_MALFORMED_REPLACEMENT; | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_UTF8: | 
					
						
							|  |  |  |     { c = get_byte(s); | 
					
						
							|  |  |  |       if ( c == EOF ) | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( c & 0x80 ) | 
					
						
							|  |  |  |       { int extra = UTF8_FBN(c); | 
					
						
							|  |  |  | 	int code; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( extra < 0 ) | 
					
						
							|  |  |  | 	{ Sseterr(s, SIO_WARN, "Illegal UTF-8 start"); | 
					
						
							|  |  |  | 	  c = UTF8_MALFORMED_REPLACEMENT; | 
					
						
							|  |  |  | 	  goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	code = UTF8_FBV(c,extra); | 
					
						
							|  |  |  | 	for( ; extra > 0; extra-- ) | 
					
						
							|  |  |  | 	{ int c2 = get_byte(s); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  if ( !ISUTF8_CB(c2) ) | 
					
						
							|  |  |  | 	  { Sseterr(s, SIO_WARN, "Illegal UTF-8 continuation"); | 
					
						
							|  |  |  | 	    c = UTF8_MALFORMED_REPLACEMENT; | 
					
						
							|  |  |  | 	    Sungetc(c2, s); | 
					
						
							|  |  |  | 	    goto out; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  code = (code<<6)+(c2&0x3f); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c = code; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_UNICODE_BE: | 
					
						
							|  |  |  |     case ENC_UNICODE_LE: | 
					
						
							|  |  |  |     { int c1, c2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c1 = get_byte(s); | 
					
						
							|  |  |  |       if ( c1 == EOF ) | 
					
						
							|  |  |  |       { c = -1; | 
					
						
							|  |  |  | 	goto out; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       c2 = get_byte(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( c2 == EOF ) | 
					
						
							|  |  |  |       { Sseterr(s, SIO_WARN, "EOF in unicode character"); | 
					
						
							|  |  |  | 	c = UTF8_MALFORMED_REPLACEMENT; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { if ( s->encoding == ENC_UNICODE_BE ) | 
					
						
							|  |  |  | 	  c = (c1<<8)+c2; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	  c = (c2<<8)+c1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ENC_WCHAR: | 
					
						
							|  |  |  |     { pl_wchar_t chr; | 
					
						
							|  |  |  |       char *p = (char*)&chr; | 
					
						
							|  |  |  |       size_t n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(n=0; n<sizeof(pl_wchar_t); n++) | 
					
						
							|  |  |  |       { int c1 = get_byte(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( c1 == EOF ) | 
					
						
							|  |  |  | 	{ if ( n == 0 ) | 
					
						
							|  |  |  | 	  { c = -1; | 
					
						
							|  |  |  | 	    goto out; | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	  { Sseterr(s, SIO_WARN, "EOF in UCS character"); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 	    c = UTF8_MALFORMED_REPLACEMENT; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    goto out; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*p++ = c1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c = chr; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       assert(0); | 
					
						
							|  |  |  |       c = -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |   if ( c == '\r' && (s->flags&SIO_TEXT) ) | 
					
						
							|  |  |  |   { switch(s->newline) | 
					
						
							|  |  |  |     { case SIO_NL_DETECT: | 
					
						
							|  |  |  | 	s->newline = SIO_NL_DOS; | 
					
						
							|  |  |  |         /*FALLTHROUGH*/ | 
					
						
							|  |  |  |       case SIO_NL_DOS: | 
					
						
							|  |  |  | 	goto retry; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->tee && s->tee->magic == SIO_MAGIC && c != -1 ) | 
					
						
							|  |  |  |     Sputcode(c, s->tee); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return S__updatefilepos(s, c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | peek needs to keep track of the actual bytes processed because not doing | 
					
						
							|  |  |  | so might lead to an  incorrect  byte-count   in  the  position term. The | 
					
						
							|  |  |  | simplest example is that when  looking   at  \r\n in Windows, get_code/1 | 
					
						
							|  |  |  | returns \n, but it returns the same for a single \n. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Often, we could keep track of bufp and reset this, but we must deal with | 
					
						
							|  |  |  | the case where we fetch a new buffer. In this case, we must copy the few | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | remaining bytes to the `unbuffer' area. If SIO_USERBUF is set, we do not | 
					
						
							|  |  |  | have this spare buffer space. This  is   used  for reading from strings, | 
					
						
							|  |  |  | which cannot fetch a new buffer anyway. | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | Speekcode(IOSTREAM *s) | 
					
						
							|  |  |  | { int c; | 
					
						
							|  |  |  |   char *start; | 
					
						
							|  |  |  |   size_t safe = (size_t)-1; | 
					
						
							|  |  |  |   if ( !s->buffer ) | 
					
						
							|  |  |  |   { if ( (s->flags & SIO_NBUF) ) | 
					
						
							|  |  |  |     { errno = EINVAL; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     if ( S__setbuf(s, NULL, 0) == (size_t)-1 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return -1; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( (s->flags & SIO_FEOF) ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( s->bufp + UNDO_SIZE > s->limitp && !(s->flags&SIO_USERBUF) ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { safe = s->limitp - s->bufp; | 
					
						
							|  |  |  |     memcpy(s->buffer-safe, s->bufp, safe); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   start = s->bufp; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( s->position ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   { IOPOS *psave = s->position; | 
					
						
							|  |  |  |     s->position = NULL; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     c = Sgetcode(s); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     s->position = psave; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   } else | 
					
						
							|  |  |  |   { c = Sgetcode(s); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( Sferror(s) ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   s->flags &= ~(SIO_FEOF|SIO_FEOF2); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s->bufp > start ) | 
					
						
							|  |  |  |   { s->bufp = start; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   } else if ( c != -1 ) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   { assert(safe != (size_t)-1); | 
					
						
							|  |  |  |     s->bufp = s->buffer-safe; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   return c; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	    PUTW/GETW		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sputw(int w, IOSTREAM *s) | 
					
						
							|  |  |  | { unsigned char *q = (unsigned char *)&w; | 
					
						
							|  |  |  |   unsigned int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(n=0; n<sizeof(w); n++) | 
					
						
							|  |  |  |   { if ( Sputc(*q++, s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return w; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sgetw(IOSTREAM *s) | 
					
						
							|  |  |  | { int w; | 
					
						
							|  |  |  |   unsigned char *q = (unsigned char *)&w; | 
					
						
							|  |  |  |   unsigned int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(n=0; n<sizeof(w); n++) | 
					
						
							|  |  |  |   { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (c = Sgetc(s)) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     *q++ = c & 0xff; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return w; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	    FREAD/FWRITE	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t | 
					
						
							|  |  |  | Sfread(void *data, size_t size, size_t elms, IOSTREAM *s) | 
					
						
							|  |  |  | { size_t chars = size * elms; | 
					
						
							|  |  |  |   char *buf = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->position ) | 
					
						
							|  |  |  |   { for( ; chars > 0; chars-- ) | 
					
						
							|  |  |  |     { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( (c = Sgetc(s)) == EOF ) | 
					
						
							|  |  |  | 	break; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       *buf++ = c & 0xff; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   } else | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { while(chars > 0) | 
					
						
							|  |  |  |     { int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |       { size_t avail = s->limitp - s->bufp; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	if ( chars <= avail ) | 
					
						
							|  |  |  | 	{ memcpy(buf, s->bufp, chars); | 
					
						
							|  |  |  | 	  s->bufp += chars; | 
					
						
							|  |  |  | 	  return elms; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 	{ memcpy(buf, s->bufp, avail); | 
					
						
							|  |  |  | 	  chars -= avail; | 
					
						
							|  |  |  | 	  buf += avail; | 
					
						
							|  |  |  | 	  s->bufp += avail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( (c = S__fillbuf(s)) == EOF ) | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *buf++ = c & 0xff; | 
					
						
							|  |  |  |       chars--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return (size*elms - chars)/size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t | 
					
						
							|  |  |  | Sfwrite(const void *data, size_t size, size_t elms, IOSTREAM *s) | 
					
						
							|  |  |  | { size_t chars = size * elms; | 
					
						
							|  |  |  |   const char *buf = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for( ; chars > 0; chars-- ) | 
					
						
							|  |  |  |   { if ( Sputc(*buf++, s) < 0 ) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return (size*elms - chars)/size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	       PENDING		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ssize_t | 
					
						
							|  |  |  | Sread_pending(IOSTREAM *s, char *buf, size_t limit, int flags) | 
					
						
							|  |  |  | { int done = 0; | 
					
						
							|  |  |  |   size_t n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->bufp >= s->limitp && (flags & SIO_RP_BLOCK) ) | 
					
						
							|  |  |  |   { int c = S__fillbuf(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( c < 0 ) | 
					
						
							|  |  |  |     { if ( (s->flags & SIO_FEOF) ) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       return c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buf[0] = c; | 
					
						
							|  |  |  |     limit--; | 
					
						
							|  |  |  |     done = 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   n = s->limitp - s->bufp; | 
					
						
							|  |  |  |   if ( n > limit ) | 
					
						
							|  |  |  |     n = limit; | 
					
						
							|  |  |  |   memcpy(&buf[done], s->bufp, n); | 
					
						
							|  |  |  |   s->bufp += n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return done+n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *               BOM		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Check the stream for a BOM (Byte Order Marker).  If present (and known), | 
					
						
							|  |  |  | update the stream encoding.  Return value is one of | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	-1:	error (check errno) | 
					
						
							|  |  |  | 	 0:	ok.  If BOM, SIO_BOM is added to flags | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { IOENC encoding; | 
					
						
							|  |  |  |   unsigned int bomlen; | 
					
						
							|  |  |  |   const char *bom; | 
					
						
							|  |  |  | } bomdef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const bomdef bomdefs[] = | 
					
						
							|  |  |  | { { ENC_UTF8,       3, "\357\273\277" }, /* 0xef, 0xbb, 0xbb */ | 
					
						
							|  |  |  |   { ENC_UNICODE_BE, 2, "\376\377" },	 /* 0xfe, oxff */ | 
					
						
							|  |  |  |   { ENC_UNICODE_LE, 2, "\377\376" },	 /* 0xff, oxfe */ | 
					
						
							|  |  |  |   { ENC_UNKNOWN,    0, NULL } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | ScheckBOM(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( (s->flags & SIO_NBUF) ) | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { size_t avail = s->limitp - s->bufp; | 
					
						
							|  |  |  |     const bomdef *bd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(bd=bomdefs; bd->bomlen; bd++) | 
					
						
							|  |  |  |     { if ( avail >= bd->bomlen && memcmp(s->bufp, bd->bom, bd->bomlen) == 0 ) | 
					
						
							|  |  |  |       { s->encoding = bd->encoding; | 
					
						
							|  |  |  | 	s->bufp += bd->bomlen; | 
					
						
							|  |  |  | 	s->flags |= SIO_BOM; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	if ( s->position ) | 
					
						
							|  |  |  | 	  s->position->byteno += bd->bomlen; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( avail >= 4 )			/* longest BOM */ | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( S__fillbuf(s) == -1 ) | 
					
						
							|  |  |  |       return 0;				/* empty stream */ | 
					
						
							|  |  |  |     s->bufp--; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | SwriteBOM(IOSTREAM *s) | 
					
						
							|  |  |  | { switch(s->encoding) | 
					
						
							|  |  |  |   { case ENC_UTF8: | 
					
						
							|  |  |  |     case ENC_UNICODE_LE: | 
					
						
							|  |  |  |     case ENC_UNICODE_BE: | 
					
						
							|  |  |  |     { if ( Sputcode(0xfeff, s) != -1 ) | 
					
						
							|  |  |  |       { s->flags |= SIO_BOM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *               FLAGS		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfeof(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->flags & SIO_FEOF ) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_NBUF ) | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( S__fillbuf(s) == -1 ) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->bufp--; | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | S__seterror(IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | { s->io_errno = errno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !(s->flags&SIO_CLOSING) &&	/* s->handle is already invalid */ | 
					
						
							|  |  |  |        s->functions->control ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { char *msg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( (*s->functions->control)(s->handle, | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 				  SIO_LASTERROR, | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 				  (void *)&msg) == 0 ) | 
					
						
							|  |  |  |     { Sseterr(s, SIO_FERR, msg); | 
					
						
							|  |  |  |       return 0; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->flags |= SIO_FERR; | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sferror(IOSTREAM *s) | 
					
						
							|  |  |  | { return (s->flags & SIO_FERR) != 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfpasteof(IOSTREAM *s) | 
					
						
							|  |  |  | { return (s->flags & (SIO_FEOF2ERR|SIO_FEOF2)) == (SIO_FEOF2ERR|SIO_FEOF2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Sclearerr(IOSTREAM *s) | 
					
						
							|  |  |  | { s->flags &= ~(SIO_FEOF|SIO_WARN|SIO_FERR|SIO_FEOF2|SIO_TIMEOUT|SIO_CLEARERR); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   s->io_errno = 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Sseterr(s, 0, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Sseterr(IOSTREAM *s, int flag, const char *message) | 
					
						
							|  |  |  | { if ( s->message ) | 
					
						
							|  |  |  |   { free(s->message); | 
					
						
							|  |  |  |     s->message = NULL; | 
					
						
							|  |  |  |     s->flags &= ~SIO_CLEARERR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( message ) | 
					
						
							|  |  |  |   { s->flags |= flag; | 
					
						
							|  |  |  |     s->message = strdup(message); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { s->flags &= ~flag; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Sset_exception(IOSTREAM *s, term_t ex) | 
					
						
							|  |  |  | { s->exception = PL_record(ex); | 
					
						
							|  |  |  |   s->flags |= SIO_FERR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Set the encoding of a stream. The enc   argument is the new encoding. If | 
					
						
							|  |  |  | old is not NULL, the old encoding is written to the given location. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Please note that not all code changing  the encoding call Ssetenc at the | 
					
						
							|  |  |  | moment. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Ssetenc(IOSTREAM *s, IOENC enc, IOENC *old) | 
					
						
							|  |  |  | { if ( old ) | 
					
						
							|  |  |  |     *old = s->encoding; | 
					
						
							|  |  |  |   if ( enc == s->encoding ) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->functions->control ) | 
					
						
							|  |  |  |   { if ( (*s->functions->control)(s->handle, | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 				  SIO_SETENCODING, | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 				  (void *)&enc) != 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->encoding = enc; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( enc == ENC_OCTET ) | 
					
						
							|  |  |  |     s->flags &= ~SIO_TEXT; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     s->flags |= SIO_TEXT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Ssetlocale(IOSTREAM *s, PL_locale *new, PL_locale **old) | 
					
						
							|  |  |  | { PL_locale *lo = s->locale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( old ) | 
					
						
							|  |  |  |     *old = s->locale; | 
					
						
							|  |  |  |   if ( new == s->locale ) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( new ) | 
					
						
							|  |  |  |     s->locale = acquireLocale(new); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     s->locale = NULL; | 
					
						
							|  |  |  |   if ( lo ) | 
					
						
							|  |  |  |     releaseLocale(lo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      FLUSH		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sflush(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->buffer && (s->flags & SIO_OUTPUT) ) | 
					
						
							|  |  |  |   { if ( S__flushbuf(s) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     if ( s->functions->control && | 
					
						
							|  |  |  | 	 (*s->functions->control)(s->handle, SIO_FLUSHOUTPUT, NULL) < 0 ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      SEEK		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sunit_size(IOSTREAM *s) | 
					
						
							|  |  |  | { switch(s->encoding) | 
					
						
							|  |  |  |   { case ENC_UNKNOWN: | 
					
						
							|  |  |  |     case ENC_OCTET: | 
					
						
							|  |  |  |     case ENC_ASCII: | 
					
						
							|  |  |  |     case ENC_ISO_LATIN_1: | 
					
						
							|  |  |  |     case ENC_ANSI: | 
					
						
							|  |  |  |     case ENC_UTF8: | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     case ENC_UNICODE_BE: | 
					
						
							|  |  |  |     case ENC_UNICODE_LE: | 
					
						
							|  |  |  |       return 2; | 
					
						
							|  |  |  |     case ENC_WCHAR: | 
					
						
							|  |  |  |       return sizeof(wchar_t); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       assert(0); | 
					
						
							|  |  |  |       return 1;				/* not reached */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Return the size of the underlying data object.  Should be optimized; | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | int64_t | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | Ssize(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->functions->control ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { int64_t size; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( (*s->functions->control)(s->handle, SIO_GETSIZE, (void *)&size) == 0 ) | 
					
						
							|  |  |  |       return size; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( s->functions->seek ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { int64_t here = Stell64(s); | 
					
						
							|  |  |  |     int64_t end; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     if ( Sseek64(s, 0, SIO_SEEK_END) == 0 ) | 
					
						
							|  |  |  |       end = Stell64(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     else | 
					
						
							|  |  |  |       end = -1; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     Sseek64(s, here, SIO_SEEK_SET); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return end; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   errno = ESPIPE; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Sseek64(IOSTREAM *s, int64_t pos, int whence) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Re-position the stream to byte-no 'pos'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Maybe we should optimise this to become block-aligned?  Or can we leave | 
					
						
							|  |  |  | this to read/write? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The first part checks whether  repositioning   the  read  pointer in the | 
					
						
							|  |  |  | buffer suffices to achieve the seek. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sseek64(IOSTREAM *s, int64_t pos, int whence) | 
					
						
							|  |  |  | { if ( (s->flags & SIO_INPUT) && s->limitp > s->buffer ) /* something there */ | 
					
						
							|  |  |  |   { int64_t now = Stell64(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( now != -1 ) | 
					
						
							|  |  |  |     { int64_t newpos; | 
					
						
							|  |  |  |       char *nbufp = (char *)-1; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( whence == SIO_SEEK_CUR ) | 
					
						
							|  |  |  |       { nbufp = s->bufp + pos; | 
					
						
							|  |  |  | 	newpos = now + pos; | 
					
						
							|  |  |  |       } else if ( whence == SIO_SEEK_SET ) | 
					
						
							|  |  |  |       { nbufp = s->bufp + (pos - now); | 
					
						
							|  |  |  | 	newpos = pos; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  | 	newpos = -1;			/* should not happen */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( nbufp >= s->buffer && nbufp < s->limitp ) | 
					
						
							|  |  |  |       { s->bufp = nbufp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pos = newpos; | 
					
						
							|  |  |  | 	goto update; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !s->functions->seek && !s->functions->seek64 ) | 
					
						
							|  |  |  |   { errno = ESPIPE; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Sflush(s); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   s->bufp   = s->buffer; | 
					
						
							|  |  |  |   if ( (s->flags & SIO_INPUT) ) | 
					
						
							|  |  |  |     s->limitp = s->buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( whence == SIO_SEEK_CUR ) | 
					
						
							|  |  |  |   { pos += Stell64(s); | 
					
						
							|  |  |  |     whence = SIO_SEEK_SET; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( s->functions->seek64 ) | 
					
						
							|  |  |  |     pos = (*s->functions->seek64)(s->handle, pos, whence); | 
					
						
							|  |  |  |   else if ( pos <= LONG_MAX ) | 
					
						
							|  |  |  |     pos = (*s->functions->seek)(s->handle, (long)pos, whence); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( pos < 0 ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | update: | 
					
						
							|  |  |  |   s->flags &= ~(SIO_FEOF|SIO_FEOF2);	/* not on eof of file anymore */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->position ) | 
					
						
							|  |  |  |   { s->flags |= (SIO_NOLINENO|SIO_NOLINEPOS); /* no update this */ | 
					
						
							|  |  |  |     s->position->byteno = pos; | 
					
						
							|  |  |  |     s->position->charno = pos/Sunit_size(s); /* compatibility */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sseek(IOSTREAM *s, long pos, int whence) | 
					
						
							|  |  |  | { return Sseek64(s, (int64_t)pos, whence); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Stell64(IOSTREAM *s) returns the current position in the file in
 | 
					
						
							|  |  |  |    bytes | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int64_t | 
					
						
							|  |  |  | Stell64(IOSTREAM *s) | 
					
						
							|  |  |  | { if ( s->position ) | 
					
						
							|  |  |  |   { return s->position->byteno; | 
					
						
							|  |  |  |   } else if ( s->functions->seek || s->functions->seek64 ) | 
					
						
							|  |  |  |   { int64_t pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( s->functions->seek64 ) | 
					
						
							|  |  |  |       pos = (*s->functions->seek64)(s->handle, 0L, SIO_SEEK_CUR); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       pos = (*s->functions->seek)(s->handle, 0L, SIO_SEEK_CUR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( s->buffer )			/* open */ | 
					
						
							|  |  |  |     { int64_t off = s->bufp - s->buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( s->flags & SIO_INPUT ) | 
					
						
							|  |  |  | 	off -= s->limitp - s->buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       pos += off; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pos; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | long | 
					
						
							|  |  |  | Stell(IOSTREAM *s) | 
					
						
							|  |  |  | { int64_t pos = Stell64(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   if ( pos == -1 ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( pos <= LONG_MAX ) | 
					
						
							|  |  |  |     return (long) pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   errno = EINVAL; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      CLOSE		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | void | 
					
						
							|  |  |  | unallocStream(IOSTREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   if ( s->mutex ) | 
					
						
							|  |  |  |   { recursiveMutexDelete(s->mutex); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     PL_free(s->mutex); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     s->mutex = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !(s->flags & SIO_STATIC) ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     PL_free(s); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | (*) Sclose() can be called recursively. For example if an XPCE object is | 
					
						
							|  |  |  | only referenced from an open stream,  the close-function will delete the | 
					
						
							|  |  |  | object, which in turn calls the  ->unlink   which  may wish to close the | 
					
						
							|  |  |  | associated stream. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_asset(void *handle); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | int | 
					
						
							|  |  |  | Sclose(IOSTREAM *s) | 
					
						
							|  |  |  | { int rval = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->magic != SIO_MAGIC )		/* already closed!? */ | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { s->io_errno = errno = EINVAL; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s->flags&SIO_CLOSING) )		/* recursive (*) */ | 
					
						
							|  |  |  |     return rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->upstream ) | 
					
						
							|  |  |  |   { Sseterr(s, SIO_FERR, "Locked by upstream filter"); | 
					
						
							|  |  |  |     reportStreamError(s); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SLOCK(s); | 
					
						
							|  |  |  |   s->flags |= SIO_CLOSING; | 
					
						
							|  |  |  |   rval = S__removebuf(s); | 
					
						
							|  |  |  |   if ( s->mbstate ) | 
					
						
							|  |  |  |     free(s->mbstate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   if ( (s->flags & SIO_ADVLOCK) ) | 
					
						
							|  |  |  |   { OVERLAPPED ov; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     HANDLE h = (HANDLE)_get_osfhandle((int)((uintptr_t)s->handle)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     memset(&ov, 0, sizeof(ov)); | 
					
						
							|  |  |  |     UnlockFileEx(h, 0, 0, 0xffffffff, &ov); | 
					
						
							|  |  |  |     s->flags &= ~SIO_ADVLOCK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   if ( s->functions->close && (*s->functions->close)(s->handle) < 0 ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { S__seterror(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     rval = -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (s->functions->close == Sclose_asset) { | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   while(s->locks > 0)			/* remove buffer-locks */ | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { int rc = Sunlock(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ( rval == 0 ) | 
					
						
							|  |  |  |       rval = rc; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( rval < 0 ) | 
					
						
							|  |  |  |     reportStreamError(s); | 
					
						
							|  |  |  |   run_close_hooks(s);			/* deletes Prolog registration */ | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   s->magic = SIO_CMAGIC; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   SUNLOCK(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   if ( s->message ) | 
					
						
							|  |  |  |     free(s->message); | 
					
						
							| 
									
										
										
										
											2014-03-15 22:29:04 +00:00
										 |  |  | #if O_LOCALE
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   if ( s->locale ) | 
					
						
							|  |  |  |     releaseLocale(s->locale); | 
					
						
							| 
									
										
										
										
											2014-03-15 22:29:04 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( s->references == 0 ) | 
					
						
							|  |  |  |     unallocStream(s); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     s->erased = TRUE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	     STRING I/O		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | Sfgets(char *buf, int n, IOSTREAM *s) | 
					
						
							|  |  |  | { char *q = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while( n-- > 0 ) | 
					
						
							|  |  |  |   { int c = Sgetc(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( c == EOF ) | 
					
						
							|  |  |  |     { *q = '\0'; | 
					
						
							|  |  |  |       if ( q == buf ) | 
					
						
							|  |  |  | 	buf = NULL; | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { *q++ = c; | 
					
						
							|  |  |  |       if ( c == '\n' ) | 
					
						
							|  |  |  |       { if ( n > 0 ) | 
					
						
							|  |  |  | 	  *q = '\0'; | 
					
						
							|  |  |  | 	goto out; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |   return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | Sgets(char *buf) | 
					
						
							|  |  |  | { char *s = Sfgets(buf, Slinesize, Sinput); | 
					
						
							|  |  |  |   char *q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s )				/* delete trailing \n */ | 
					
						
							|  |  |  |   { q = &s[strlen(s)]; | 
					
						
							|  |  |  |     if ( q > s && q[-1] == '\n' ) | 
					
						
							|  |  |  |       *--q = '\0'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfputs(const char *q, IOSTREAM *s) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | { for( ; *q; q++) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { if ( Sputcode(*q&0xff, s) < 0 ) | 
					
						
							|  |  |  |       return EOF; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sputs(const char *q) | 
					
						
							|  |  |  | { return Sfputs(q, Soutput); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	       PRINTF		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfprintf(IOSTREAM *s, const char *fm, ...) | 
					
						
							|  |  |  | { va_list args; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, fm); | 
					
						
							|  |  |  |   rval = Svfprintf(s, fm, args); | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sprintf(const char *fm, ...) | 
					
						
							|  |  |  | { va_list args; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, fm); | 
					
						
							|  |  |  |   rval = Svfprintf(Soutput, fm, args); | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Svprintf(const char *fm, va_list args) | 
					
						
							|  |  |  | { return Svfprintf(Soutput, fm, args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #define NEXTCHR(s, c)				\
 | 
					
						
							|  |  |  | 	switch (enc)				\ | 
					
						
							|  |  |  | 	{ case ENC_ANSI:			\ | 
					
						
							|  |  |  | 	    c = *(s)++; c &= 0xff;		\ | 
					
						
							|  |  |  | 	    break;				\ | 
					
						
							|  |  |  | 	  case ENC_UTF8:			\ | 
					
						
							|  |  |  | 	    (s) = utf8_get_char((s), &(c));	\ | 
					
						
							|  |  |  | 	    break;				\ | 
					
						
							|  |  |  | 	  case ENC_WCHAR:			\ | 
					
						
							|  |  |  | 	  { wchar_t *_w = (wchar_t*)(s);	\ | 
					
						
							|  |  |  | 	    c = *_w++;				\ | 
					
						
							|  |  |  | 	    (s) = (char*)_w;			\ | 
					
						
							|  |  |  | 	    break;				\ | 
					
						
							|  |  |  | 	  }					\ | 
					
						
							|  |  |  | 	  default:				\ | 
					
						
							| 
									
										
										
										
											2013-11-15 10:38:00 +00:00
										 |  |  |             c = '\0';				\ | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	    break;				\ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define OUTCHR(s, c)	do { printed++; \
 | 
					
						
							|  |  |  | 			     if ( Sputcode((c), (s)) < 0 ) goto error; \ | 
					
						
							|  |  |  | 			   } while(0) | 
					
						
							|  |  |  | #define valdigit(c)	((c) - '0')
 | 
					
						
							|  |  |  | #define A_LEFT	0			/* left-aligned field */
 | 
					
						
							|  |  |  | #define A_RIGHT 1			/* right-aligned field */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | #define SNPRINTF3(fm, a1) \
 | 
					
						
							|  |  |  | 	{ size_t __r; \ | 
					
						
							|  |  |  | 	  assert(fs == fbuf); \ | 
					
						
							|  |  |  | 	  __r = snprintf(fs, sizeof(fbuf), fm, a1); \ | 
					
						
							|  |  |  | 	  if ( __r >= sizeof(fbuf) ) \ | 
					
						
							|  |  |  | 	  { if ( (fs_malloced = fs = malloc(__r+1)) == NULL ) goto error; \ | 
					
						
							|  |  |  | 	    __r = snprintf(fs, __r+1, fm, a1); \ | 
					
						
							|  |  |  | 	  } \ | 
					
						
							|  |  |  | 	  fe = fs+__r; \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #define SNPRINTF4(fm, a1, a2) \
 | 
					
						
							|  |  |  | 	{ size_t __r; \ | 
					
						
							|  |  |  | 	  assert(fs == fbuf); \ | 
					
						
							|  |  |  | 	  __r = snprintf(fs, sizeof(fbuf), fm, a1, a2); \ | 
					
						
							|  |  |  | 	  if ( __r >= sizeof(fbuf) ) \ | 
					
						
							|  |  |  | 	  { if ( (fs_malloced = fs = malloc(__r+1)) == NULL ) goto error; \ | 
					
						
							|  |  |  | 	    __r = snprintf(fs, __r+1, fm, a1, a2); \ | 
					
						
							|  |  |  | 	  } \ | 
					
						
							|  |  |  | 	  fe = fs+__r; \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | int | 
					
						
							|  |  |  | Svfprintf(IOSTREAM *s, const char *fm, va_list args) | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | { int printed = 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   char buf[TMPBUFSIZE]; | 
					
						
							|  |  |  |   int tmpbuf; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   char *fs_malloced = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   SLOCK(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !s->buffer && (s->flags & SIO_NBUF) ) | 
					
						
							|  |  |  |   { S__setbuf(s, buf, sizeof(buf)); | 
					
						
							|  |  |  |     tmpbuf = TRUE; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     tmpbuf = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while(*fm) | 
					
						
							|  |  |  |   { if ( *fm == '%' ) | 
					
						
							|  |  |  |     { fm++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( *fm == '%' ) | 
					
						
							|  |  |  |       { OUTCHR(s, *fm); | 
					
						
							|  |  |  | 	fm++; | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { int align = A_RIGHT; | 
					
						
							|  |  |  | 	int modified = FALSE; | 
					
						
							|  |  |  | 	int has_arg1 = FALSE, has_arg2 = FALSE; | 
					
						
							|  |  |  | 	int arg1=0, arg2=0; | 
					
						
							|  |  |  | 	char fbuf[100], *fs = fbuf, *fe = fbuf; | 
					
						
							|  |  |  | 	int islong = 0; | 
					
						
							|  |  |  | 	int pad = ' '; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	IOENC enc = ENC_ANSI; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ switch(*fm) | 
					
						
							|  |  |  | 	  { case '+':	align = A_RIGHT; fm++; continue; | 
					
						
							|  |  |  | 	    case '-':	align = A_LEFT;  fm++; continue; | 
					
						
							|  |  |  | 	    case '0':	pad = '0';	 fm++; continue; | 
					
						
							|  |  |  | 	    case ' ':	pad = ' ';       fm++; continue; | 
					
						
							|  |  |  | 	    case '#':   modified = TRUE; fm++; continue; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( *fm == '*' ) | 
					
						
							|  |  |  | 	{ has_arg1++; | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  arg1 = va_arg(args, int); | 
					
						
							|  |  |  | 	} else if ( isdigit(char_to_int(*fm)) ) | 
					
						
							|  |  |  | 	{ if ( *fm == '0' ) | 
					
						
							|  |  |  | 	    pad = '0'; | 
					
						
							|  |  |  | 	  arg1 = valdigit(*fm); | 
					
						
							|  |  |  | 	  has_arg1++; | 
					
						
							|  |  |  | 	  for( fm++; isdigit(char_to_int(*fm)); fm++) | 
					
						
							|  |  |  | 	    arg1 = arg1*10 + valdigit(*fm); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ( *fm == '.' ) | 
					
						
							|  |  |  | 	{ has_arg2++; | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  if ( *fm == '*' ) | 
					
						
							|  |  |  | 	  { arg2 = va_arg(args, int); | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	  { arg2 = 0; | 
					
						
							|  |  |  | 	    for( ; isdigit(char_to_int(*fm)); fm++) | 
					
						
							|  |  |  | 	      arg2 = arg2*10 + valdigit(*fm); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( *fm == 'l' ) | 
					
						
							|  |  |  | 	{ islong++;			/* 1: %ld */ | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	switch ( *fm ) | 
					
						
							|  |  |  | 	{ case 'l': | 
					
						
							|  |  |  | 	    islong++;			/* 2: %lld */ | 
					
						
							|  |  |  | 	    fm++; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  case 'U':			/* %Us: UTF-8 string */ | 
					
						
							|  |  |  | 	    enc = ENC_UTF8; | 
					
						
							|  |  |  | 	    fm++; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  case 'W':			/* %Ws: wide string */ | 
					
						
							|  |  |  | 	    enc = ENC_WCHAR; | 
					
						
							|  |  |  | 	    fm++; | 
					
						
							|  |  |  | 	    break; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(*fm) | 
					
						
							|  |  |  | 	{ case 'c': | 
					
						
							|  |  |  | 	    *fe++ = va_arg(args, int); | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  case 'p': | 
					
						
							|  |  |  | 	  { void *ptr = va_arg(args, void*); | 
					
						
							|  |  |  | 	    char fmbuf[8], *fp=fmbuf; | 
					
						
							|  |  |  | 	    *fp++ = '%'; | 
					
						
							|  |  |  | 	    if ( modified ) | 
					
						
							|  |  |  | 	      *fp++ = '#'; | 
					
						
							|  |  |  | 	    *fp++ = 'p'; | 
					
						
							|  |  |  | 	    *fp   = '\0'; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    SNPRINTF3(fmbuf, ptr); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case 'd': | 
					
						
							|  |  |  | 	  case 'i': | 
					
						
							|  |  |  | 	  case 'o': | 
					
						
							|  |  |  | 	  case 'u': | 
					
						
							|  |  |  | 	  case 'x': | 
					
						
							|  |  |  | 	  case 'X': | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	  { int      vi = 0; | 
					
						
							|  |  |  | 	    long     vl = 0;			/* make compiler silent */ | 
					
						
							|  |  |  | 	    int64_t vll = 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    char fmbuf[8], *fp=fmbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    switch( islong ) | 
					
						
							|  |  |  | 	    { case 0: | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 		vi = va_arg(args, int); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	        break; | 
					
						
							|  |  |  | 	      case 1: | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 		vl = va_arg(args, long); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	        break; | 
					
						
							|  |  |  | 	      case 2: | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	        vll = va_arg(args, int64_t); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	      default: | 
					
						
							|  |  |  | 		assert(0); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    *fp++ = '%'; | 
					
						
							|  |  |  | 	    if ( modified ) | 
					
						
							|  |  |  | 	      *fp++ = '#'; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	    switch( islong ) | 
					
						
							|  |  |  | 	    { case 0: | 
					
						
							|  |  |  | 		*fp++ = *fm; | 
					
						
							|  |  |  | 	        *fp   = '\0'; | 
					
						
							|  |  |  | 		SNPRINTF3(fmbuf, vi); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	      case 1: | 
					
						
							|  |  |  | 		*fp++ = 'l'; | 
					
						
							|  |  |  | 	        *fp++ = *fm; | 
					
						
							|  |  |  | 		*fp   = '\0'; | 
					
						
							|  |  |  | 		SNPRINTF3(fmbuf, vl); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	      case 2: | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef __WINDOWS__
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	        *fp++ = 'I';		/* Synchronise with INT64_FORMAT! */ | 
					
						
							|  |  |  | 	        *fp++ = '6'; | 
					
						
							|  |  |  | 		*fp++ = '4'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	        *fp++ = 'l'; | 
					
						
							|  |  |  | 	        *fp++ = 'l'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	        *fp++ = *fm; | 
					
						
							|  |  |  | 	        *fp   = '\0'; | 
					
						
							|  |  |  | 	        SNPRINTF3(fmbuf, vll); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case 'f': | 
					
						
							|  |  |  | 	  case 'e': | 
					
						
							|  |  |  | 	  case 'E': | 
					
						
							|  |  |  | 	  case 'g': | 
					
						
							|  |  |  | 	  case 'G': | 
					
						
							|  |  |  | 	  { double v = va_arg(args, double); | 
					
						
							|  |  |  | 	    char fmbuf[8], *fp=fmbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    *fp++ = '%'; | 
					
						
							|  |  |  | 	    if ( modified ) | 
					
						
							|  |  |  | 	      *fp++ = '#'; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    if ( has_arg2 )		/* specified precission */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    { *fp++ = '.'; | 
					
						
							|  |  |  | 	      *fp++ = '*'; | 
					
						
							|  |  |  | 	      *fp++ = *fm; | 
					
						
							|  |  |  | 	      *fp   = '\0'; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	      SNPRINTF4(fmbuf, arg2, v); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    } else | 
					
						
							|  |  |  | 	    { *fp++ = *fm; | 
					
						
							|  |  |  | 	      *fp   = '\0'; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	      SNPRINTF3(fmbuf, v); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	    fe = &fs[strlen(fs)]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case 's': | 
					
						
							|  |  |  | 	    fs = va_arg(args, char *); | 
					
						
							|  |  |  | 	    if ( !fs ) | 
					
						
							|  |  |  | 	      fs = "(null)"; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( has_arg1 )			/* aligned field */ | 
					
						
							|  |  |  | 	{ if ( fs == fbuf ) | 
					
						
							|  |  |  | 	    *fe = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( align == A_LEFT ) | 
					
						
							|  |  |  | 	  { int w = 0; | 
					
						
							|  |  |  | 	    while(*fs) | 
					
						
							|  |  |  | 	    { int c; | 
					
						
							|  |  |  | 	      NEXTCHR(fs, c); | 
					
						
							|  |  |  | 	      OUTCHR(s, c); | 
					
						
							|  |  |  | 	      w++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    while(w < arg1) | 
					
						
							|  |  |  | 	    { OUTCHR(s, pad); | 
					
						
							|  |  |  | 	      w++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } else /*if ( align == A_RIGHT ) */ | 
					
						
							|  |  |  | 	  { size_t w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( fs == fbuf ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 	    { w = fe - fs; | 
					
						
							|  |  |  | 	    } else | 
					
						
							|  |  |  | 	    { switch(enc) | 
					
						
							|  |  |  | 	      { case ENC_ANSI: | 
					
						
							|  |  |  | 		  w = strlen(fs); | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		case ENC_UTF8: | 
					
						
							|  |  |  | 		  w = strlen(fs); | 
					
						
							|  |  |  | 		  w = utf8_strlen(fs, w); | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		case ENC_WCHAR: | 
					
						
							|  |  |  | 		  w = wcslen((wchar_t*)fs); | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 		  assert(0); | 
					
						
							|  |  |  | 		  w = 0;		/* make compiler happy */ | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    if ( (ssize_t)w < arg1 ) | 
					
						
							|  |  |  | 	    { w = arg1 - w; | 
					
						
							|  |  |  | 	      while(w > 0 ) | 
					
						
							|  |  |  | 	      { OUTCHR(s, pad); | 
					
						
							|  |  |  | 		w--; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    while(*fs) | 
					
						
							|  |  |  | 	    { int c; | 
					
						
							|  |  |  | 	      NEXTCHR(fs, c); | 
					
						
							|  |  |  | 	      OUTCHR(s, c); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 	{ if ( fs == fbuf )		/* unaligned field, just output */ | 
					
						
							|  |  |  | 	  { while(fs < fe) | 
					
						
							|  |  |  | 	      OUTCHR(s, *fs++); | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	  { while(*fs) | 
					
						
							|  |  |  | 	    { int c; | 
					
						
							|  |  |  | 	      NEXTCHR(fs, c); | 
					
						
							|  |  |  | 	      OUTCHR(s, c); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fm++; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	if ( fs_malloced ) | 
					
						
							|  |  |  | 	{ fs_malloced = NULL; | 
					
						
							|  |  |  | 	  free(fs_malloced); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } else if ( *fm == '\\' && fm[1] ) | 
					
						
							|  |  |  |     { OUTCHR(s, fm[1]); | 
					
						
							|  |  |  |       fm += 2; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { OUTCHR(s, *fm); | 
					
						
							|  |  |  |       fm++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( tmpbuf ) | 
					
						
							|  |  |  |   { if ( S__removebuf(s) < 0 ) | 
					
						
							|  |  |  |       goto error; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SUNLOCK(s); | 
					
						
							|  |  |  |   return (int)printed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   if ( fs_malloced ) | 
					
						
							|  |  |  |     free(fs_malloced); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   SUNLOCK(s); | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Ssprintf(char *buf, const char *fm, ...) | 
					
						
							|  |  |  | { va_list args; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, fm); | 
					
						
							|  |  |  |   rval = Svsprintf(buf, fm, args); | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Svsprintf(char *buf, const char *fm, va_list args) | 
					
						
							|  |  |  | { IOSTREAM s; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset(&s, 0, sizeof(s)); | 
					
						
							|  |  |  |   s.bufp      = buf; | 
					
						
							|  |  |  |   s.limitp    = (char *)(~0L); | 
					
						
							|  |  |  |   s.buffer    = buf; | 
					
						
							|  |  |  |   s.flags     = SIO_FBUF|SIO_OUTPUT; | 
					
						
							|  |  |  |   s.encoding  = ENC_ISO_LATIN_1; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( (rval = Svfprintf(&s, fm, args)) >= 0 ) | 
					
						
							|  |  |  |     *s.bufp = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Svdprintf(const char *fm, va_list args) | 
					
						
							|  |  |  | { int rval; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   IOSTREAM *s = Serror; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   Slock(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   rval = Svfprintf(s, fm, args); | 
					
						
							|  |  |  | #if defined(_DEBUG) && defined(__WINDOWS__)
 | 
					
						
							|  |  |  |   Sputc('\0', s); | 
					
						
							|  |  |  |   s->bufp--;				/* `Unput' */ | 
					
						
							|  |  |  |   OutputDebugString(s->buffer); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   if ( Sflush(s) != 0 ) | 
					
						
							|  |  |  |     rval = -1; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   Sunlock(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sdprintf(const char *fm, ...) | 
					
						
							|  |  |  | { va_list args; | 
					
						
							|  |  |  |   int rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, fm); | 
					
						
							|  |  |  |   rval = Svdprintf(fm, args); | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      SCANF		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Svfscanf(IOSTREAM *s, const char *fm, va_list args) | 
					
						
							|  |  |  | { int done = 0;				/* # items converted */ | 
					
						
							|  |  |  |   int chread = 0;			/* # characters read */ | 
					
						
							|  |  |  |   int c = GET(s);			/* current character */ | 
					
						
							|  |  |  |   int supress;				/* if TRUE, don't assign (*) */ | 
					
						
							|  |  |  |   int field_width;			/* max width of field */ | 
					
						
							|  |  |  |   int tsize;				/* SZ_SHORT, SZ_NORMAL, SZ_LONG */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while(*fm) | 
					
						
							|  |  |  |   { if ( *fm == ' ' ) | 
					
						
							|  |  |  |     { while ( isblank(c) ) | 
					
						
							|  |  |  | 	c = GET(s); | 
					
						
							|  |  |  |       fm++; | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } else if ( *fm == '%' && fm[1] != '%' ) | 
					
						
							|  |  |  |     { supress = FALSE; | 
					
						
							|  |  |  |       field_width = -1; | 
					
						
							|  |  |  |       int size = SZ_STANDARD; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(;;)				/* parse modifiers */ | 
					
						
							|  |  |  |       { fm++; | 
					
						
							|  |  |  | 	if ( isdigit(*fm) ) | 
					
						
							|  |  |  | 	{ field_width = valdigit(*fm); | 
					
						
							|  |  |  | 	  for(++fm; isdigit(*fm); fm++) | 
					
						
							|  |  |  | 	    field_width = 10*field_width + valdigit(*fm); | 
					
						
							|  |  |  | 	  fm--; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ( *fm == '*' ) | 
					
						
							|  |  |  | 	{ supress++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ( *fm == 'l' ) | 
					
						
							|  |  |  | 	{ size = SZ_LONG; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ( *fm == 'h' ) | 
					
						
							|  |  |  | 	{ size = SZ_SHORT; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( *fm != '[' && *fm != c ) | 
					
						
							|  |  |  | 	while(isblank(c)) | 
					
						
							|  |  |  | 	  c = GET(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       switch(*fm) | 
					
						
							|  |  |  |       { { intptr_t v;			/* collect value here */ | 
					
						
							|  |  |  | 	  int negative;			/* true if < 0 */ | 
					
						
							|  |  |  | 	  int base;			/* base for conversion */ | 
					
						
							|  |  |  | 	  int ok;			/* successful */ | 
					
						
							|  |  |  | 	case 'd': | 
					
						
							|  |  |  | 	  base = 10; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do_int: | 
					
						
							|  |  |  | 	  negative = FALSE; | 
					
						
							|  |  |  | 	  if ( c == '+' ) | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	  else if ( c == '-' ) | 
					
						
							|  |  |  | 	  { negative++; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	do_unsigned: | 
					
						
							|  |  |  | 	  ok = FALSE; | 
					
						
							|  |  |  | 	  if ( base == 16 )		/* hexadecimal */ | 
					
						
							|  |  |  | 	  { if ( isxdigit(c) ) | 
					
						
							|  |  |  | 	    { v = valxdigit(c); | 
					
						
							|  |  |  | 	      for(c = GET(s); isxdigit(c); c = GET(s)) | 
					
						
							|  |  |  | 		v = base*v + valxdigit(c); | 
					
						
							|  |  |  | 	      ok++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	  { int cv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( isdigit(c) && (cv=valdigit(c)) < base ) | 
					
						
							|  |  |  | 	    { v = cv; | 
					
						
							|  |  |  | 	      for(c = GET(s); isdigit(c) && (cv=valdigit(c)) < base; c = GET(s)) | 
					
						
							|  |  |  | 		v = base*v + cv; | 
					
						
							|  |  |  | 	      ok++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( ok ) | 
					
						
							|  |  |  | 	  { if ( !supress ) | 
					
						
							|  |  |  | 	    { if ( negative ) | 
					
						
							|  |  |  | 		v = -v; | 
					
						
							|  |  |  | 	      if ( tsize == SZ_SHORT ) | 
					
						
							|  |  |  | 	      { short *vp = va_arg(args, short *); | 
					
						
							|  |  |  | 		*vp = v; | 
					
						
							|  |  |  | 	      } else if ( tsize == SZ_LONG ) | 
					
						
							|  |  |  | 	      { intptr_t *vp = va_arg(args, intptr_t *); | 
					
						
							|  |  |  | 		*vp = v; | 
					
						
							|  |  |  | 	      } else | 
					
						
							|  |  |  | 	      { int *vp = va_arg(args, int *); | 
					
						
							|  |  |  | 		*vp = v; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	      done++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    continue;			/* with next */ | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	    return done; | 
					
						
							|  |  |  | 	case 'u': | 
					
						
							|  |  |  | 	  base = 10; | 
					
						
							|  |  |  | 	  negative = FALSE; | 
					
						
							|  |  |  | 	  goto do_unsigned; | 
					
						
							|  |  |  | 	case 'o': | 
					
						
							|  |  |  | 	  base = 8; | 
					
						
							|  |  |  | 	  goto do_int; | 
					
						
							|  |  |  | 	case 'x': | 
					
						
							|  |  |  | 	  base = 16; | 
					
						
							|  |  |  | 	  goto do_int; | 
					
						
							|  |  |  | 	case 'i': | 
					
						
							|  |  |  | 	  if ( c == '0' ) | 
					
						
							|  |  |  | 	  { int c2 = GET(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( c2 == 'x' ) | 
					
						
							|  |  |  | 	    { base = 16; | 
					
						
							|  |  |  | 	      c = GET(s); | 
					
						
							|  |  |  | 	    } else | 
					
						
							|  |  |  | 	    { UNGET(c2, s); | 
					
						
							|  |  |  | 	      base = 8; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    negative = FALSE; | 
					
						
							|  |  |  | 	    goto do_unsigned; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  base = 10; | 
					
						
							|  |  |  | 	  goto do_int; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	case 'n': | 
					
						
							|  |  |  | 	  if ( !supress ) | 
					
						
							|  |  |  | 	  { if ( tsize == SZ_SHORT ) | 
					
						
							|  |  |  | 	    { short *vp = va_arg(args, short *); | 
					
						
							|  |  |  | 	      *vp = chread; | 
					
						
							|  |  |  | 	    } else if ( tsize == SZ_LONG ) | 
					
						
							|  |  |  | 	    { intptr_t *vp = va_arg(args, intptr_t *); | 
					
						
							|  |  |  | 	      *vp = chread; | 
					
						
							|  |  |  | 	    } else | 
					
						
							|  |  |  | 	    { int *vp = va_arg(args, int *); | 
					
						
							|  |  |  | 	      *vp = chread; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    done++; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	case 'E': | 
					
						
							|  |  |  | 	case 'e': | 
					
						
							|  |  |  | 	case 'f': | 
					
						
							|  |  |  | 	case 'G': | 
					
						
							|  |  |  | 	case 'g': | 
					
						
							|  |  |  | 	{ char work[200]; | 
					
						
							|  |  |  | 	  char *w = work; | 
					
						
							|  |  |  | 	  int ds = 0; | 
					
						
							|  |  |  | 	  double v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( c == '-' || c == '+' )	/* [+|-] */ | 
					
						
							|  |  |  | 	  { *w++ = c; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  while(isdigit(c))		/* {digit} */ | 
					
						
							|  |  |  | 	  { *w++ = c; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	    ds++; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  if ( c == '.' )		/* [.] */ | 
					
						
							|  |  |  | 	    *w++ = c; | 
					
						
							|  |  |  | 	  while(isdigit(c))		/* {digit} */ | 
					
						
							|  |  |  | 	  { *w++ = c; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	    ds++; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  if ( !ds ) | 
					
						
							|  |  |  | 	    SCAN_ERROR(s) | 
					
						
							|  |  |  | 	  if ( c == 'e' || c == 'E' )	/* [e<digit>{<digit>}] */ | 
					
						
							|  |  |  | 	  { *w++ = c; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	    if ( !isdigit(c) ) | 
					
						
							|  |  |  | 	      SCAN_ERROR(s) | 
					
						
							|  |  |  | 	    while(isdigit(c)) | 
					
						
							|  |  |  | 	    { *w++ = c; | 
					
						
							|  |  |  | 	    c = GET(s); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if ( !supress ) | 
					
						
							|  |  |  | 	  { *w = '\0'; | 
					
						
							|  |  |  | 	    v = strtod(work, &w) | 
					
						
							|  |  |  | 	    if ( w == work ) | 
					
						
							|  |  |  | 	      SCAN_ERROR(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    switch(tsize) | 
					
						
							|  |  |  | 	    { case SZ_NORMAL: | 
					
						
							|  |  |  | 	      { float *fp = va_arg(args, float *); | 
					
						
							|  |  |  | 		*fp = v; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 	      } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	      case SZ_LONG: | 
					
						
							|  |  |  | 	      { double *fp = va_arg(args, double *); | 
					
						
							|  |  |  | 		*fp = v; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	      } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    done++; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	case 's': | 
					
						
							|  |  |  | 	  if ( !supress ) | 
					
						
							|  |  |  | 	  { char *sp = va_arg(args, char *); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	    while(!isblank(c) && field_width-- != 0) | 
					
						
							|  |  |  | 	    { *sp++ = c; | 
					
						
							|  |  |  | 	      c = GET(s); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  } else | 
					
						
							|  |  |  | 	    while(!isblank(c) && field_width-- != 0) | 
					
						
							|  |  |  | 	      c = GET(s); | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	case 'c': | 
					
						
							|  |  |  | 	  if ( !supress ) | 
					
						
							|  |  |  | 	  { char *cp = va_arg(args, char *); | 
					
						
							|  |  |  | 	    *cp = c; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  c = GET(s); | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	case '[': | 
					
						
							|  |  |  | 	{ char set[256]; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  memset(set, 0, sizeof(set)); | 
					
						
							|  |  |  | 	  fm++; | 
					
						
							|  |  |  | 	  if ( *fm == ']' ) | 
					
						
							|  |  |  | 	    set[*fm++]++; | 
					
						
							|  |  |  | 	  else if ( *fm == '^' ) | 
					
						
							|  |  |  | 	  { fm++; | 
					
						
							|  |  |  | 	    negate++; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  while(*fm != ']') | 
					
						
							|  |  |  | 	  { if ( *fm == '-' ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else				/* normal character */ | 
					
						
							|  |  |  |     { if ( c == *fm ) | 
					
						
							|  |  |  |       { c = GET(s); | 
					
						
							|  |  |  | 	fm++; | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |   UNGET(c, s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return done; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /*0*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	   FILTER STREAMS	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Link two streams in a pipeline,  where   filter  filters data for stream | 
					
						
							|  |  |  | `parent'. If parent is an output steam we have | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	application --> filter --> parent --> | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | If parent is an input stream we have | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	--> parent --> filter --> application | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sset_filter(IOSTREAM *parent, IOSTREAM *filter) | 
					
						
							|  |  |  | { if ( !parent || parent->magic != SIO_MAGIC ) | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( filter ) | 
					
						
							|  |  |  |   { if ( filter->magic != SIO_MAGIC ) | 
					
						
							|  |  |  |     { errno = EINVAL; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   parent->upstream = filter; | 
					
						
							|  |  |  |   if ( filter ) | 
					
						
							|  |  |  |     filter->downstream = parent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	    FILE STREAMS	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_file(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  |   ssize_t bytes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |     bytes = read((int)h, buf, (int)size); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     bytes = read((int)h, buf, size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( bytes == -1 && errno == EINTR ) | 
					
						
							|  |  |  |     { if ( PL_handle_signals() < 0 ) | 
					
						
							|  |  |  |       { errno = EPLEXCEPTION; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return bytes; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-15 22:22:11 +00:00
										 |  |  |   return -1; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_file(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  |   ssize_t bytes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(;;) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |     bytes = write((int)h, buf, (int)size); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     bytes = write((int)h, buf, size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if ( bytes == -1 && errno == EINTR ) | 
					
						
							|  |  |  |     { if ( PL_handle_signals() < 0 ) | 
					
						
							|  |  |  |       { errno = EPLEXCEPTION; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return bytes; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | Sseek_file(void *handle, long pos, int whence) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* cannot do EINTR according to man */ | 
					
						
							|  |  |  |   return lseek((int)h, pos, whence); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_LARGEFILES
 | 
					
						
							|  |  |  | static int64_t | 
					
						
							|  |  |  | Sseek_file64(void *handle, int64_t pos, int whence) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* cannot do EINTR according to man */ | 
					
						
							|  |  |  |   return lseek((int)h, pos, whence); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_file(void *handle) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  |   int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   do | 
					
						
							|  |  |  |   { rc = close((int) h); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   } while ( rc == -1 && errno == EINTR ); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Scontrol_file(void *handle, int action, void *arg) | 
					
						
							|  |  |  | { intptr_t h = (intptr_t) handle; | 
					
						
							|  |  |  |   int fd = (int)h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(action) | 
					
						
							|  |  |  |   { case SIO_GETSIZE: | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     { int64_t *rval = arg; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       struct stat buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( fstat(fd, &buf) == 0 ) | 
					
						
							|  |  |  |       {	*rval = buf.st_size; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SIO_SETENCODING: | 
					
						
							|  |  |  |     case SIO_FLUSHOUTPUT: | 
					
						
							|  |  |  |       return 0; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     case SIO_GETFILENO: | 
					
						
							|  |  |  |     { int *p = arg; | 
					
						
							|  |  |  |       *p = fd; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOFUNCTIONS Sfilefunctions = | 
					
						
							|  |  |  | { Sread_file, | 
					
						
							|  |  |  |   Swrite_file, | 
					
						
							|  |  |  |   Sseek_file, | 
					
						
							|  |  |  |   Sclose_file, | 
					
						
							|  |  |  |   Scontrol_file, | 
					
						
							|  |  |  | #ifdef O_LARGEFILES
 | 
					
						
							|  |  |  |   Sseek_file64 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   NULL | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOFUNCTIONS Sttyfunctions = | 
					
						
							|  |  |  | { Sread_file, | 
					
						
							|  |  |  |   Swrite_file, | 
					
						
							|  |  |  |   NULL, | 
					
						
							|  |  |  |   Sclose_file, | 
					
						
							|  |  |  |   Scontrol_file, | 
					
						
							|  |  |  | #ifdef O_LARGEFILES
 | 
					
						
							|  |  |  |   Sseek_file64 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   NULL | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | (*)  Windows  isatty()  is  totally  broken   since  VC9;  crashing  the | 
					
						
							|  |  |  | application instead of returning EINVAL on  wrong   values  of fd. As we | 
					
						
							|  |  |  | provide  the  socket-id  through   Sfileno,    this   code   crashes  on | 
					
						
							|  |  |  | tcp_open_socket(). As ttys and its detection is   of no value on Windows | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | anyway, we skip this. | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | For now, we use PL_malloc_uncollectable(). In   the  end, this is really | 
					
						
							|  |  |  | one of the object-types we want to leave to GC. | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #ifndef FD_CLOEXEC			/* This is not defined in MacOS */
 | 
					
						
							|  |  |  | #define FD_CLOEXEC 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | IOSTREAM * | 
					
						
							|  |  |  | Snew(void *handle, int flags, IOFUNCTIONS *functions) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( !(s = PL_malloc_uncollectable(sizeof(IOSTREAM))) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { errno = ENOMEM; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   memset((char *)s, 0, sizeof(IOSTREAM)); | 
					
						
							|  |  |  |   s->magic         = SIO_MAGIC; | 
					
						
							|  |  |  |   s->lastc         = EOF; | 
					
						
							|  |  |  |   s->flags         = flags; | 
					
						
							|  |  |  |   s->handle        = handle; | 
					
						
							|  |  |  |   s->functions     = functions; | 
					
						
							|  |  |  |   s->timeout       = -1;		/* infinite */ | 
					
						
							|  |  |  |   s->posbuf.lineno = 1; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   if ( (flags&SIO_TEXT) ) | 
					
						
							|  |  |  |   { s->encoding    = initEncoding(); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { s->encoding	   = ENC_OCTET; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #if CRLF_MAPPING
 | 
					
						
							|  |  |  |   s->newline       = SIO_NL_DOS; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   if ( flags & SIO_RECORDPOS ) | 
					
						
							|  |  |  |     s->position = &s->posbuf; | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   if ( !(flags & SIO_NOMUTEX) ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { if ( !(s->mutex = PL_malloc(sizeof(recursiveMutex))) ) | 
					
						
							|  |  |  |     { PL_free(s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     recursiveMutexInit(s->mutex); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | { int fd; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   if ( (fd = Sfileno(s)) >= 0 ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   { | 
					
						
							|  |  |  | #ifndef __WINDOWS__			/* (*) */
 | 
					
						
							|  |  |  |     if ( isatty(fd) ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |       s->flags |= SIO_ISATTY; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(F_SETFD)
 | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     fcntl(fd, F_SETFD, FD_CLOEXEC); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #elif defined(__WINDOWS__)
 | 
					
						
							|  |  |  |     SetHandleInformation((HANDLE)_get_osfhandle(fd), | 
					
						
							|  |  |  | 			 HANDLE_FLAG_INHERIT, 0); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  |   initStreamLocale(s); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef O_BINARY
 | 
					
						
							|  |  |  | #define O_BINARY 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Open a file. In addition to the normal  arguments, "lr" means get a read | 
					
						
							|  |  |  | (shared-) lock on the file and  "lw"   means  get  an write (exclusive-) | 
					
						
							|  |  |  | lock.  How much do we need to test here? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that the low-level open  is  always   binary  as  O_TEXT open files | 
					
						
							|  |  |  | result in lost and corrupted data in   some  encodings (UTF-16 is one of | 
					
						
							|  |  |  | them).  Sgetcode()  and  Sputcode()  do  the  LF  <->  CRLF  mapping  of | 
					
						
							|  |  |  | CRLF_MAPPING is defined. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							|  |  |  | Sopen_file(const char *path, const char *how) | 
					
						
							|  |  |  | { int fd; | 
					
						
							|  |  |  |   int oflags = O_BINARY; | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   int flags = SIO_FILE|SIO_TEXT|SIO_RECORDPOS|SIO_FBUF; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int op = *how++; | 
					
						
							|  |  |  |   intptr_t lfd; | 
					
						
							|  |  |  |   enum {lnone=0,lread,lwrite} lock = lnone; | 
					
						
							|  |  |  |   IOSTREAM *s; | 
					
						
							|  |  |  |   IOENC enc = ENC_UNKNOWN; | 
					
						
							| 
									
										
										
										
											2014-06-16 14:44:04 +01:00
										 |  |  | #if __WINDOWS__
 | 
					
						
							|  |  |  |   int wait = TRUE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if __ANDROID__
 | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  |   if (Yap_isAsset(path)) { | 
					
						
							|  |  |  |       extern IOFUNCTIONS Sassetfunctions; | 
					
						
							|  |  |  |       extern void *Yap_openAssetFile(const char *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (op != 'r') | 
					
						
							|  |  |  |           return NULL; | 
					
						
							|  |  |  |       for( ; *how; how++) | 
					
						
							|  |  |  |       { switch(*how) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |               case 'b':				/* binary */ | 
					
						
							|  |  |  |               flags &= ~SIO_TEXT; | 
					
						
							|  |  |  |               enc = ENC_OCTET; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |               case 'r':				/* no record */ | 
					
						
							|  |  |  |               flags &= ~SIO_RECORDPOS; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |               default: | 
					
						
							|  |  |  |               errno = EINVAL; | 
					
						
							|  |  |  |               return NULL; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | #if O_LARGEFILES && defined(O_LARGEFILE)
 | 
					
						
							|  |  |  |   oflags |= O_LARGEFILE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       lfd = (intptr_t)Yap_openAssetFile( path ); | 
					
						
							|  |  |  |       if (!lfd) { | 
					
						
							|  |  |  |           errno = EINVAL; | 
					
						
							|  |  |  |           return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       Sfilefunctions = Sassetfunctions; | 
					
						
							|  |  |  |       lock = 0; | 
					
						
							|  |  |  |       flags |= SIO_INPUT; | 
					
						
							|  |  |  |       goto build_stream; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for( ; *how; how++) | 
					
						
							|  |  |  |   { switch(*how) | 
					
						
							|  |  |  |     { case 'b':				/* binary */ | 
					
						
							|  |  |  | 	flags &= ~SIO_TEXT; | 
					
						
							|  |  |  | 	enc = ENC_OCTET; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case 'r':				/* no record */ | 
					
						
							|  |  |  | 	flags &= ~SIO_RECORDPOS; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2014-06-16 14:44:04 +01:00
										 |  |  | #if __WINDOWS__
 | 
					
						
							|  |  |  |      case 'L':				/* lock r: read, w: write */ | 
					
						
							|  |  |  | 	wait = FALSE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |         /*FALLTHROUGH*/ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       case 'l':				/* lock r: read, w: write */ | 
					
						
							|  |  |  | 	if ( *++how == 'r' ) | 
					
						
							|  |  |  | 	  lock = lread; | 
					
						
							|  |  |  |         else if ( *how == 'w' ) | 
					
						
							|  |  |  | 	  lock = lwrite; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  | 	{ errno = EINVAL; | 
					
						
							|  |  |  | 	  return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  | 	errno = EINVAL; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if O_LARGEFILES && defined(O_LARGEFILE)
 | 
					
						
							|  |  |  |   oflags |= O_LARGEFILE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(op) | 
					
						
							|  |  |  |   { case 'w': | 
					
						
							|  |  |  |       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|oflags, 0666); | 
					
						
							|  |  |  |       flags |= SIO_OUTPUT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 'a': | 
					
						
							|  |  |  |       fd = open(path, O_WRONLY|O_CREAT|O_APPEND|oflags, 0666); | 
					
						
							|  |  |  |       flags |= SIO_OUTPUT|SIO_APPEND; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 'u': | 
					
						
							|  |  |  |       fd = open(path, O_WRONLY|O_CREAT|oflags, 0666); | 
					
						
							|  |  |  |       flags |= SIO_OUTPUT|SIO_UPDATE; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 'r': | 
					
						
							|  |  |  |       fd = open(path, O_RDONLY|oflags); | 
					
						
							|  |  |  |       flags |= SIO_INPUT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       errno = EINVAL; | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( fd < 0 ) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( lock ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef FCNTL_LOCKS
 | 
					
						
							|  |  |  |     struct flock buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memset(&buf, 0, sizeof(buf)); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     buf.l_whence = SEEK_SET; | 
					
						
							|  |  |  |     buf.l_type   = (lock == lread ? F_RDLCK : F_WRLCK); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     while( fcntl(fd, wait ? F_SETLKW : F_SETLK, &buf) != 0 ) | 
					
						
							|  |  |  |     { if ( errno == EINTR ) | 
					
						
							|  |  |  |       { if ( PL_handle_signals() < 0 ) | 
					
						
							|  |  |  | 	{ close(fd); | 
					
						
							|  |  |  | 	  return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       } else | 
					
						
							|  |  |  |       { int save = errno; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	close(fd); | 
					
						
							|  |  |  | 	errno = save; | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #else					/* we don't have locking */
 | 
					
						
							|  |  |  | #if __WINDOWS__
 | 
					
						
							|  |  |  |     HANDLE h = (HANDLE)_get_osfhandle(fd); | 
					
						
							|  |  |  |     OVERLAPPED ov; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     int flags = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( lock == lwrite ) | 
					
						
							|  |  |  |       flags |= LOCKFILE_EXCLUSIVE_LOCK; | 
					
						
							|  |  |  |     if ( !wait ) | 
					
						
							|  |  |  |       flags |= LOCKFILE_FAIL_IMMEDIATELY; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     memset(&ov, 0, sizeof(ov)); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |     if ( !LockFileEx(h, flags, | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		     0, | 
					
						
							|  |  |  | 		     0, 0xfffffff, | 
					
						
							|  |  |  | 		     &ov) ) | 
					
						
							|  |  |  |     { close(fd); | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |       errno = (wait ? EACCES : EAGAIN);	/* TBD: proper error */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     close(fd); | 
					
						
							|  |  |  |     errno = EINVAL; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   lfd = (intptr_t)fd; | 
					
						
							| 
									
										
										
										
											2015-04-13 13:28:17 +01:00
										 |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  |  build_stream: | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   s = Snew((void *)lfd, flags, &Sfilefunctions); | 
					
						
							|  |  |  |   if ( enc != ENC_UNKNOWN ) | 
					
						
							|  |  |  |     s->encoding = enc; | 
					
						
							|  |  |  |   if ( lock ) | 
					
						
							|  |  |  |     s->flags |= SIO_ADVLOCK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							|  |  |  | Sfdopen(int fd, const char *type) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | { intptr_t lfd; | 
					
						
							|  |  |  |   int flags = SIO_FILE|SIO_RECORDPOS|SIO_FBUF; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( fd < 0 ) | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #if defined(HAVE_FCNTL) && defined(F_GETFL)
 | 
					
						
							|  |  |  |   if ( fcntl(fd, F_GETFL) == -1 ) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( *type == 'r' ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { flags |= SIO_INPUT; | 
					
						
							|  |  |  |   } else if ( *type == 'w' ) | 
					
						
							|  |  |  |   { flags |= SIO_OUTPUT; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( type[1] != 'b' ) | 
					
						
							|  |  |  |     flags |= SIO_TEXT; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   lfd = (intptr_t)fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return Snew((void *)lfd, flags, &Sfilefunctions); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* MT: as long as s is valid, this should be ok
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sfileno(IOSTREAM *s) | 
					
						
							|  |  |  | { int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_FILE ) | 
					
						
							|  |  |  |   { intptr_t h = (intptr_t)s->handle; | 
					
						
							|  |  |  |     n = (int)h; | 
					
						
							|  |  |  |   } else if ( s->functions->control && | 
					
						
							|  |  |  | 	      (*s->functions->control)(s->handle, | 
					
						
							|  |  |  | 				       SIO_GETFILENO, | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 				       (void *)&n) == 0 ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { ; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     n = -1;				/* no file stream */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | On  Windows,  type  SOCKET  is   an    unsigned   int   and  all  values | 
					
						
							|  |  |  | [0..INVALID_SOCKET) are valid. It is  also   not  allowed  to run normal | 
					
						
							|  |  |  | file-functions on it or the application will crash. There seems to be no | 
					
						
							|  |  |  | way out except for introducing an extra function at this level :-( | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SOCKET | 
					
						
							|  |  |  | Swinsock(IOSTREAM *s) | 
					
						
							|  |  |  | { SOCKET n = INVALID_SOCKET; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->functions->control && | 
					
						
							|  |  |  |        (*s->functions->control)(s->handle, | 
					
						
							|  |  |  | 				SIO_GETWINSOCK, | 
					
						
							|  |  |  | 				(void *)&n) == 0 ) | 
					
						
							|  |  |  |   { return n; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   errno = EINVAL; | 
					
						
							|  |  |  |   return INVALID_SOCKET; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	       PIPES		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_POPEN
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | #include "windows/popen.c"
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 17:55:27 +01:00
										 |  |  | #undef popen
 | 
					
						
							|  |  |  | #undef pclose
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #define popen(cmd, how) pt_popen(cmd, how)
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #define pclose(fd)	pt_pclose(fd)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_pipe(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { FILE *fp = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   return read(fileno(fp), buf, (unsigned int)size); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   return read(fileno(fp), buf, size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_pipe(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { FILE *fp = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |   return write(fileno(fp), buf, (unsigned int)size); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   return write(fileno(fp), buf, size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_pipe(void *handle) | 
					
						
							|  |  |  | { FILE *fp = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pclose(fp); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | Scontrol_pipe(void *handle, int action, void *arg) | 
					
						
							|  |  |  | { FILE *fp = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(action) | 
					
						
							|  |  |  |   { case SIO_GETFILENO: | 
					
						
							|  |  |  |     { int *ap = arg; | 
					
						
							|  |  |  |       *ap = fileno(fp); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SIO_FLUSHOUTPUT: | 
					
						
							|  |  |  |     case SIO_SETENCODING: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | IOFUNCTIONS Spipefunctions = | 
					
						
							|  |  |  | { Sread_pipe, | 
					
						
							|  |  |  |   Swrite_pipe, | 
					
						
							|  |  |  |   (Sseek_function)0, | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   Sclose_pipe, | 
					
						
							|  |  |  |   Scontrol_pipe | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							|  |  |  | Sopen_pipe(const char *command, const char *type) | 
					
						
							|  |  |  | { char mode[2]; | 
					
						
							|  |  |  |   FILE *fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |   Sdprintf("Opening \"%s\", mode \"%s\" --> %p (%d)\n", | 
					
						
							|  |  |  | 	   command, type, fd, errno); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mode[0] = type[0]; | 
					
						
							|  |  |  |   mode[1] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (fd = popen(command, mode)) ) | 
					
						
							|  |  |  |   { int flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( *type == 'r' ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       flags = SIO_INPUT|SIO_RECORDPOS|SIO_FBUF; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       flags = SIO_OUTPUT|SIO_RECORDPOS|SIO_FBUF; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return Snew((void *)fd, flags, &Spipefunctions); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /*HAVE_POPEN*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if __ANDROID__
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	  ASSET FILES		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Asset files provide a mechanism for accesing file resources stored in | 
					
						
							|  |  |  | an Android application pack. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_asset(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return -1L; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_asset(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-06-11 19:33:18 +01:00
										 |  |  |   int res = AAsset_read((AAsset* )handle, (void* )buf, size); | 
					
						
							| 
									
										
										
										
											2014-06-04 22:08:37 +01:00
										 |  |  |   if (res < 0) { | 
					
						
							|  |  |  |       errno = ENOSPC;			/* signal error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | Sseek_asset(void *handle, long offset, int whence) | 
					
						
							|  |  |  | { int res = AAsset_seek((AAsset* )handle, (off_t)offset, whence); | 
					
						
							|  |  |  |   if (res == (off_t)-1) { | 
					
						
							|  |  |  |       errno = ENOSPC;			/* signal error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int64_t | 
					
						
							|  |  |  | Sseek64_asset(void *handle, int64_t offset, int whence) | 
					
						
							|  |  |  | { off64_t res = AAsset_seek64((AAsset* )handle, (off64_t)offset, whence); | 
					
						
							|  |  |  |   if (res == (off64_t)-1) { | 
					
						
							|  |  |  |       errno = ENOSPC;			/* signal error */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Scontrol_asset(void *handle, int action, void *arg) | 
					
						
							|  |  |  | { AAsset*  h = (AAsset* ) handle; | 
					
						
							|  |  |  |   off_t *rval = (off_t *)arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(action) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case SIO_GETSIZE: | 
					
						
							|  |  |  |       *rval = AAsset_getLength(h); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     case SIO_GETFILENO: | 
					
						
							|  |  |  |         { off_t start = 0, end = AAsset_getLength(h); | 
					
						
							|  |  |  | 	  int fd = AAsset_openFileDescriptor((AAsset*)handle, &start, &end); | 
					
						
							|  |  |  | 	  if (fd == 0) | 
					
						
							|  |  |  | 	     return -1; | 
					
						
							|  |  |  | 	  *rval = fd; | 
					
						
							|  |  |  | 	  return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 	  case SIO_SETENCODING: | 
					
						
							|  |  |  |     case SIO_FLUSHOUTPUT: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_asset(void *handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   AAsset_close((AAsset* )handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOFUNCTIONS Sassetfunctions = | 
					
						
							|  |  |  | { Sread_asset, | 
					
						
							|  |  |  |   Swrite_asset, | 
					
						
							|  |  |  |   Sseek_asset, | 
					
						
							|  |  |  |   Sclose_asset, | 
					
						
							|  |  |  |   Scontrol_asset, | 
					
						
							|  |  |  |   Sseek64_asset | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <jni.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Sopen_asset(char **buffer, size_t *sizep, const char* mode) | 
					
						
							|  |  |  |     Open an Android asset, essentially a read-only 	part of a ZIP archive. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* __ANDROID__ */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	  MEMORY STREAMS	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Memory streams form a replacement for   sprintf(), sscanf() and friends. | 
					
						
							|  |  |  | They allow regarding a piece of  (for output) malloc() maintained memory | 
					
						
							|  |  |  | to serve as a temporary buffer. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MT: we assume these handles are not passed between threads | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { size_t	here;			/* `here' location */ | 
					
						
							|  |  |  |   size_t	size;			/* size of buffer */ | 
					
						
							|  |  |  |   size_t       *sizep;			/* pointer to size */ | 
					
						
							|  |  |  |   size_t	allocated;		/* allocated size */ | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   char	       *buffer;			/* allocated buffer */ | 
					
						
							|  |  |  |   char	      **bufferp;		/* Write-back location */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int		malloced;		/* malloc() maintained */ | 
					
						
							|  |  |  | } memfile; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Sfree(void *ptr)			/* Windows: must free from same */ | 
					
						
							|  |  |  | { free(ptr);				/* DLL */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static size_t | 
					
						
							|  |  |  | S__memfile_nextsize(size_t needed) | 
					
						
							|  |  |  | { size_t size = 512; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ( size < needed ) | 
					
						
							|  |  |  |     size *= 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_memfile(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { memfile *mf = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( mf->here + size + 1 >= mf->allocated ) | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |   { size_t ns = S__memfile_nextsize(mf->here + size + 1); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     char *nb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( mf->allocated == 0 || !mf->malloced ) | 
					
						
							|  |  |  |     { if ( !(nb = malloc(ns)) ) | 
					
						
							|  |  |  |       { errno = ENOMEM; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if ( !mf->malloced ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       { if ( mf->buffer ) | 
					
						
							|  |  |  | 	  memcpy(nb, mf->buffer, mf->allocated); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	mf->malloced = TRUE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     { if ( !(nb = realloc(mf->buffer, ns)) ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       { errno = ENOMEM; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mf->allocated = ns; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     *mf->bufferp = mf->buffer = nb; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   memcpy(&mf->buffer[mf->here], buf, size); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   mf->here += size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( mf->here > mf->size ) | 
					
						
							|  |  |  |   { mf->size = mf->here; | 
					
						
							|  |  |  |     if ( mf->sizep )			/* make externally known */ | 
					
						
							|  |  |  |       *mf->sizep = mf->size; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     mf->buffer[mf->size] = '\0'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_memfile(void *handle, char *buf, size_t size) | 
					
						
							|  |  |  | { memfile *mf = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( size + mf->here > mf->size ) | 
					
						
							|  |  |  |   { if ( mf->here > mf->size ) | 
					
						
							|  |  |  |       size = 0; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       size = mf->size - mf->here; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   memcpy(buf, &mf->buffer[mf->here], size); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   mf->here += size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | Sseek_memfile(void *handle, long offset, int whence) | 
					
						
							|  |  |  | { memfile *mf = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(whence) | 
					
						
							|  |  |  |   { case SIO_SEEK_SET: | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case SIO_SEEK_CUR: | 
					
						
							|  |  |  |       offset += (long)mf->here;		/* Win64: truncates */ | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case SIO_SEEK_END: | 
					
						
							|  |  |  |       offset = (long)mf->size - offset;	/* Win64 */ | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       errno = EINVAL; | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( offset < 0 || offset > (long)mf->size ) | 
					
						
							|  |  |  |   { errno = EINVAL; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   mf->here = offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return offset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_memfile(void *handle) | 
					
						
							|  |  |  | { memfile *mf = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( mf ) | 
					
						
							|  |  |  |   { free(mf); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   errno = EINVAL;			/* not opened */ | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOFUNCTIONS Smemfunctions = | 
					
						
							|  |  |  | { Sread_memfile, | 
					
						
							|  |  |  |   Swrite_memfile, | 
					
						
							|  |  |  |   Sseek_memfile, | 
					
						
							|  |  |  |   Sclose_memfile | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Sopenmem(char **buffer, size_t *sizep, const char* mode) | 
					
						
							|  |  |  |     Open a memory area as a stream.  Output streams will automatically | 
					
						
							|  |  |  |     resized using realloc() if *size = 0 or the stream is opened with mode | 
					
						
							|  |  |  |     "wa". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If the buffer is allocated or enlarged, this is achieved using malloc() | 
					
						
							|  |  |  |     or realloc().  In this case the returned buffer should be freed by the | 
					
						
							|  |  |  |     caller when done.  Example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { char buf[1024];			(don't allocate for small stuff) | 
					
						
							|  |  |  |       char *s = buf; | 
					
						
							|  |  |  |       IOSTREAM *fd; | 
					
						
							|  |  |  |       size_t size = sizeof(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fd = Sopenmem(&s, &size, "w"); | 
					
						
							|  |  |  |       ... | 
					
						
							|  |  |  |       Sclose(fd); | 
					
						
							|  |  |  |       ... | 
					
						
							|  |  |  |       if ( s != buf )			(appearently moved) | 
					
						
							|  |  |  | 	Sfree(s); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note: Its is NOT allows to access   streams  created with this call from | 
					
						
							|  |  |  | multiple threads. This is ok for all   usage inside Prolog itself (often | 
					
						
							|  |  |  | through tellString()/toldString(). This call is   intented  to use write | 
					
						
							|  |  |  | and other output predicates to create strings. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | Sopenmem(char **bufp, size_t *sizep, const char *mode) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { memfile *mf = malloc(sizeof(memfile)); | 
					
						
							|  |  |  |   int flags = SIO_FBUF|SIO_RECORDPOS|SIO_NOMUTEX; | 
					
						
							|  |  |  |   size_t size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !mf ) | 
					
						
							|  |  |  |   { errno = ENOMEM; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mf->malloced = FALSE; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   mf->bufferp  = bufp; | 
					
						
							|  |  |  |   mf->buffer   = *bufp; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   switch(*mode) | 
					
						
							|  |  |  |   { case 'r': | 
					
						
							|  |  |  |       flags |= SIO_INPUT; | 
					
						
							|  |  |  |       if ( sizep == NULL || *sizep == (size_t)-1 ) | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	size = (mf->buffer ? strlen(mf->buffer) : 0); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	size = *sizep; | 
					
						
							|  |  |  |       mf->size = size; | 
					
						
							|  |  |  |       mf->allocated = size+1; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 'w': | 
					
						
							|  |  |  |       flags |= SIO_OUTPUT; | 
					
						
							|  |  |  |       mf->size = 0; | 
					
						
							|  |  |  |       mf->allocated = (sizep ? *sizep : 0); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       if ( mf->buffer == NULL || mode[1] == 'a' ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	mf->malloced = TRUE; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       if ( mf->buffer ) | 
					
						
							|  |  |  | 	mf->buffer[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       if ( sizep ) | 
					
						
							|  |  |  | 	*sizep = mf->size; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       free(mf); | 
					
						
							|  |  |  |       errno = EINVAL; | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mf->sizep	= sizep; | 
					
						
							|  |  |  |   mf->here      = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return Snew(mf, flags, &Smemfunctions); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	      STRINGS		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* MT: we assume these handles are not passed between threads
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Sread_string(void *handle, char *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  |   (void)buf; | 
					
						
							|  |  |  |   (void)size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0;				/* signal EOF */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | Swrite_string(void *handle, char *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { (void)handle; | 
					
						
							|  |  |  |   (void)buf; | 
					
						
							|  |  |  |   (void)size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   errno = ENOSPC;			/* signal error */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Sclose_string(void *handle) | 
					
						
							|  |  |  | { IOSTREAM *s = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->flags & SIO_OUTPUT ) | 
					
						
							|  |  |  |   { if ( s->bufp < s->limitp ) | 
					
						
							|  |  |  |     { *s->bufp++ = '\0'; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { errno = ENOSPC;			/* signal error */ | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     return 0;				/* input string */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOFUNCTIONS Sstringfunctions = | 
					
						
							|  |  |  | { Sread_string, | 
					
						
							|  |  |  |   Swrite_string, | 
					
						
							|  |  |  |   (Sseek_function)0, | 
					
						
							|  |  |  |   Sclose_string | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							|  |  |  | Sopen_string(IOSTREAM *s, char *buf, size_t size, const char *mode) | 
					
						
							|  |  |  | { int flags = SIO_FBUF|SIO_USERBUF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !s ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { if ( !(s = PL_malloc_uncollectable(sizeof(IOSTREAM))) ) /* TBD: Use GC */ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     { errno = ENOMEM; | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     flags |= SIO_STATIC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset((char *)s, 0, sizeof(IOSTREAM)); | 
					
						
							|  |  |  |   s->timeout   = -1; | 
					
						
							|  |  |  |   s->buffer    = buf; | 
					
						
							|  |  |  |   s->bufp      = buf; | 
					
						
							|  |  |  |   s->unbuffer  = buf; | 
					
						
							|  |  |  |   s->handle    = s;			/* for Sclose_string() */ | 
					
						
							|  |  |  |   s->functions = &Sstringfunctions; | 
					
						
							|  |  |  |   s->encoding  = ENC_ISO_LATIN_1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch(*mode) | 
					
						
							|  |  |  |   { case 'r': | 
					
						
							|  |  |  |       if ( size == (size_t)-1 ) | 
					
						
							|  |  |  | 	size = strlen(buf); | 
					
						
							|  |  |  |       flags |= SIO_INPUT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 'w': | 
					
						
							|  |  |  |       flags |= SIO_OUTPUT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       errno = EINVAL; | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->flags  = flags; | 
					
						
							|  |  |  |   s->limitp = &buf[size]; | 
					
						
							|  |  |  |   s->magic  = SIO_MAGIC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	 STANDARD HANDLES	* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define STDIO(n, f) { NULL, NULL, NULL, NULL, \
 | 
					
						
							|  |  |  | 		      EOF, SIO_MAGIC, 0, f, {0, 0, 0}, NULL, \ | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 		      (void *)(n), &Sttyfunctions, \ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 		      0, NULL, \ | 
					
						
							|  |  |  | 		      (void (*)(void *))0, NULL, \ | 
					
						
							|  |  |  | 		      -1, \ | 
					
						
							|  |  |  | 		      0, \ | 
					
						
							|  |  |  | 		      ENC_ISO_LATIN_1 \ | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SIO_STDIO (SIO_FILE|SIO_STATIC|SIO_NOCLOSE|SIO_ISATTY|SIO_TEXT)
 | 
					
						
							|  |  |  | #define STDIO_STREAMS \
 | 
					
						
							|  |  |  |   STDIO(0, SIO_STDIO|SIO_LBUF|SIO_INPUT|SIO_NOFEOF),	/* Sinput */ \ | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   STDIO(1, SIO_STDIO|SIO_LBUF|SIO_OUTPUT|SIO_REPPL),	/* Soutput */ \ | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   STDIO(2, SIO_STDIO|SIO_NBUF|SIO_OUTPUT|SIO_REPPL)	/* Serror */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM S__iob[] = | 
					
						
							|  |  |  | { STDIO_STREAMS | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const IOSTREAM S__iob0[] = | 
					
						
							|  |  |  | { STDIO_STREAMS | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | static int S__initialised = FALSE; | 
					
						
							| 
									
										
										
										
											2011-08-22 15:45:49 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2011-03-28 22:55:28 +01:00
										 |  |  | SinitStreams(void) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { if ( !S__initialised ) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { int i; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     IOENC enc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     S__initialised = TRUE; | 
					
						
							|  |  |  |     enc = initEncoding(); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for(i=0; i<=2; i++) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     { IOSTREAM *s = &S__iob[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |       if ( !isatty(i) && s->functions == &Sttyfunctions ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       { s->flags &= ~SIO_ISATTY; | 
					
						
							| 
									
										
										
										
											2014-02-20 10:38:18 +00:00
										 |  |  | 	    s->functions = &Sfilefunctions; /* Check for pipe? */ | 
					
						
							|  |  |  | #if HAVE_SETLINEBUF
 | 
					
						
							|  |  |  | 	    /* make sure wwe buffer on new line for ttys, eg eclipse console */ | 
					
						
							|  |  |  |       } else if (i == 1) { | 
					
						
							| 
									
										
										
										
											2015-02-09 01:53:28 +00:00
										 |  |  | 	setlinebuf( stdout ); | 
					
						
							| 
									
										
										
										
											2014-02-20 10:38:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-02-20 10:38:18 +00:00
										 |  |  |       if ( s > 0) | 
					
						
							|  |  |  | 	s->newline = SIO_NL_DOS; | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       if ( s->encoding == ENC_ISO_LATIN_1 ) | 
					
						
							|  |  |  | 	s->encoding = enc; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef O_PLMT
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       s->mutex = PL_malloc(sizeof(recursiveMutex)); | 
					
						
							|  |  |  |       recursiveMutexInit(s->mutex); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if CRLF_MAPPING
 | 
					
						
							|  |  |  |       _setmode(i, O_BINARY); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       s->newline = SIO_NL_DOS; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __WINDOWS__
 | 
					
						
							|  |  |  |     pt_init();				/* init popen() issues */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IOSTREAM * | 
					
						
							| 
									
										
										
										
											2013-01-19 14:40:08 +00:00
										 |  |  | S__getiob(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { return S__iob; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	       HOOKS		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | This allows external packages (Prolog itself) to monitor the destruction | 
					
						
							|  |  |  | of streams. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _close_hook | 
					
						
							|  |  |  | { struct _close_hook *next; | 
					
						
							|  |  |  |   void (*hook)(IOSTREAM *s); | 
					
						
							|  |  |  | } close_hook; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static close_hook *close_hooks; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | run_close_hooks(IOSTREAM *s) | 
					
						
							|  |  |  | { close_hook *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(p=close_hooks; p; p = p->next) | 
					
						
							|  |  |  |     (*p->hook)(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( s->close_hook ) | 
					
						
							|  |  |  |     (*s->close_hook)(s->closure); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | Sclosehook(void (*hook)(IOSTREAM *s)) | 
					
						
							|  |  |  | { close_hook *h = malloc(sizeof(*h)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !h ) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   h->next = close_hooks; | 
					
						
							|  |  |  |   h->hook = hook; | 
					
						
							|  |  |  |   close_hooks = h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	       CLEANUP		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Sreset(void) | 
					
						
							|  |  |  | { IOSTREAM *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( (s=Sinput) && s->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |   { s->bufp = s->limitp = s->buffer; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( (s=Soutput) && s->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |   { s->bufp = s->buffer; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ( (s=Serror) && s->magic == SIO_MAGIC ) | 
					
						
							|  |  |  |   { s->bufp = s->buffer; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | Scleanup(void) | 
					
						
							|  |  |  | { close_hook *p, *next; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(p=close_hooks; p; p=next) | 
					
						
							|  |  |  |   { next = p->next; | 
					
						
							|  |  |  |     free(p); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   close_hooks = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(i=0; i<=2; i++) | 
					
						
							|  |  |  |   { IOSTREAM *s = &S__iob[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->bufp = s->buffer;		/* avoid actual flush */ | 
					
						
							|  |  |  |     S__removebuf(s); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |     if ( S__iob[i].mutex ) | 
					
						
							|  |  |  |     { recursiveMutex *m = S__iob[i].mutex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       S__iob[i].mutex = NULL; | 
					
						
							|  |  |  |       recursiveMutexDelete(m); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       PL_free(m); | 
					
						
							| 
									
										
										
										
											2010-02-22 17:59:23 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     *s = S__iob0[i];			/* re-initialise */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   S__initialised = FALSE; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } |