1 /*  Part of SWI-Prolog
2 
3     Author:        Jan Wielemaker
4     E-mail:        J.Wielemaker@vu.nl
5     WWW:           http://www.swi-prolog.org
6     Copyright (c)  2011-2017, University of Amsterdam
7                               VU University Amsterdam
8     All rights reserved.
9 
10     Redistribution and use in source and binary forms, with or without
11     modification, are permitted provided that the following conditions
12     are met:
13 
14     1. Redistributions of source code must retain the above copyright
15        notice, this list of conditions and the following disclaimer.
16 
17     2. Redistributions in binary form must reproduce the above copyright
18        notice, this list of conditions and the following disclaimer in
19        the documentation and/or other materials provided with the
20        distribution.
21 
22     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33     POSSIBILITY OF SUCH DAMAGE.
34 */
35 
36 #ifndef _PL_STREAM_H
37 #define _PL_STREAM_H
38 
39 /* This appears to make the wide-character support compile and work
40    on HPUX 11.23.  There really should be a cleaner way ...
41 */
42 #if defined(__hpux)
43 #include <sys/_mbstate_t.h>
44 #endif
45 
46 #ifndef __WINDOWS__
47 #if defined(_MSC_VER) || defined(__MINGW32__)
48 #define __WINDOWS__ 1
49 #endif
50 #endif
51 
52 #ifdef __MINGW32__
53 #include <winsock2.h>
54 #include <windows.h>
55 #endif
56 
57 #include <stdarg.h>
58 #include <wchar.h>
59 #include <stddef.h>
60 #ifdef _MSC_VER
61 typedef __int64 int64_t;
62 #if (_MSC_VER < 1300)
63 typedef long intptr_t;
64 typedef unsigned long uintptr_t;
65 #endif
66 typedef intptr_t ssize_t;		/* signed version of size_t */
67 #else
68 #include <unistd.h>
69 #include <inttypes.h>			/* more portable than stdint.h */
70 #endif
71 
72 #ifdef __cplusplus
73 extern "C" {
74 #endif
75 
76 		 /*******************************
77 		 *	       EXPORT		*
78 		 *******************************/
79 
80 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81 See SWI-Prolog.h, containing the same code   for  an explanation on this
82 stuff.
83 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
84 
85 #ifndef _PL_EXPORT_DONE
86 #define _PL_EXPORT_DONE
87 
88 #if defined(_MSC_VER) || defined(__MINGW32__)
89 #define HAVE_DECLSPEC
90 #endif
91 
92 #ifdef HAVE_DECLSPEC
93 # ifdef PL_KERNEL
94 #define PL_EXPORT(type)		__declspec(dllexport) type
95 #define PL_EXPORT_DATA(type)	__declspec(dllexport) type
96 #define install_t		void
97 # else
98 #  ifdef __BORLANDC__
99 #define PL_EXPORT(type)		type _stdcall
100 #define PL_EXPORT_DATA(type)	extern type
101 #  else
102 #   ifdef __MINGW32__
103 #define PL_EXPORT(type)		extern type
104 #define PL_EXPORT_DATA(type)	extern type
105 #   else
106 #define PL_EXPORT(type)		extern type
107 #define PL_EXPORT_DATA(type)	__declspec(dllimport) type
108 #   endif
109 #  endif
110 #define install_t		__declspec(dllexport) void
111 # endif
112 #else /*HAVE_DECLSPEC*/
113 #define PL_EXPORT(type)		extern type
114 #define PL_EXPORT_DATA(type)	extern type
115 #define install_t		void
116 #endif /*HAVE_DECLSPEC*/
117 #endif /*_PL_EXPORT_DONE*/
118 
119 		 /*******************************
120 		 *	    CONSTANTS		*
121 		 *******************************/
122 
123 #ifndef EOF
124 #define EOF (-1)
125 #endif
126 
127 #ifndef NULL
128 #define NULL ((void *)0)
129 #endif
130 
131 #if defined(__WINDOWS__) && !defined(EWOULDBLOCK)
132 #define EWOULDBLOCK	140		/* Needed for socket handling */
133 					/* 140 is compatible to VS2010 */
134 #endif
135 #define EPLEXCEPTION	1001		/* errno: pending Prolog exception */
136 
137 #define SIO_BUFSIZE	(4096)		/* buffering buffer-size */
138 #define SIO_LINESIZE	(1024)		/* Sgets() default buffer size */
139 #define SIO_OMAGIC	(7212676)	/* old magic number */
140 #define SIO_MAGIC	(7212677)	/* magic number */
141 #define SIO_CMAGIC	(42)		/* we are close (and thus illegal!) */
142 
143 typedef ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize);
144 typedef ssize_t (*Swrite_function)(void *handle, char*buf, size_t bufsize);
145 typedef long  (*Sseek_function)(void *handle, long pos, int whence);
146 typedef int64_t (*Sseek64_function)(void *handle, int64_t pos, int whence);
147 typedef int   (*Sclose_function)(void *handle);
148 typedef int   (*Scontrol_function)(void *handle, int action, void *arg);
149 
150 #if defined(O_PLMT) && defined(PL_KERNEL)
151 #include "pl-mutex.h"
152 #define IOLOCK recursiveMutex
153 #else
154 typedef void *		IOLOCK;		/* Definition for external use */
155 #endif
156 
157 #ifndef PL_HAVE_TERM_T
158 #define PL_HAVE_TERM_T
159 typedef uintptr_t	term_t;		/* opaque term handle */
160 #endif
161 
162 typedef struct io_functions
163 { Sread_function	read;		/* fill the buffer */
164   Swrite_function	write;		/* empty the buffer */
165   Sseek_function	seek;		/* seek to position */
166   Sclose_function	close;		/* close stream */
167   Scontrol_function	control;	/* Info/control */
168   Sseek64_function	seek64;		/* seek to position (large files) */
169 } IOFUNCTIONS;
170 
171 typedef struct io_position
172 { int64_t		byteno;		/* byte-position in file */
173   int64_t		charno;		/* character position in file */
174   int			lineno;		/* lineno in file */
175   int			linepos;	/* position in line */
176   intptr_t		reserved[2];	/* future extensions */
177 } IOPOS;
178 
179 					/* NOTE: check with encoding_names */
180 					/* in pl-file.c */
181 typedef enum
182 { ENC_UNKNOWN = 0,			/* invalid/unknown */
183   ENC_OCTET,				/* raw 8 bit input */
184   ENC_ASCII,				/* US-ASCII (0..127) */
185   ENC_ISO_LATIN_1,			/* ISO Latin-1 (0..256) */
186   ENC_ANSI,				/* default (multibyte) codepage */
187   ENC_UTF8,
188   ENC_UNICODE_BE,			/* big endian unicode file */
189   ENC_UNICODE_LE,			/* little endian unicode file */
190   ENC_WCHAR				/* pl_wchar_t */
191 } IOENC;
192 
193 #define SIO_NL_POSIX  0			/* newline as \n */
194 #define SIO_NL_DOS    1			/* newline as \r\n */
195 #define SIO_NL_DETECT 3			/* detect processing mode */
196 
197 typedef struct io_stream
198 { char		       *bufp;		/* `here' */
199   char		       *limitp;		/* read/write limit */
200   char		       *buffer;		/* the buffer */
201   char		       *unbuffer;	/* Sungetc buffer */
202   int			lastc;		/* last character written */
203   int			magic;		/* magic number SIO_MAGIC */
204   int			bufsize;	/* size of the buffer */
205   int			flags;		/* Status flags */
206   IOPOS			posbuf;		/* location in file */
207   IOPOS *		position;	/* pointer to above */
208   void		       *handle;		/* function's handle */
209   IOFUNCTIONS	       *functions;	/* open/close/read/write/seek */
210   int			timeout;	/* timeout (milliseconds) */
211   IOENC			encoding;	/* character encoding used */
212   int		        locks;		/* lock/unlock count */
213   int			references;	/* Reference-count */
214   IOLOCK *		mutex;		/* stream mutex */
215   void			(*close_hook)(void* closure);
216   void *		closure;
217   mbstate_t *		mbstate;	/* ENC_ANSI decoding */
218   struct io_stream *	tee;		/* copy data to this stream */
219   struct io_stream *	upstream;	/* stream providing our input */
220   struct io_stream *	downstream;	/* stream providing our output */
221   unsigned		newline : 2;	/* Newline mode */
222   unsigned		erased : 1;	/* Stream was erased */
223   int			io_errno;	/* Save errno value */
224   char *		message;	/* error/warning message */
225   void *		exception;	/* pending exception (record_t) */
226   void *		context;	/* getStreamContext() */
227   struct PL_locale *	locale;		/* Locale associated to stream */
228   intptr_t		reserved[4];	/* reserved for extension */
229 } IOSTREAM;
230 
231 
232 #define SmakeFlag(n)	(1<<(n-1))
233 
234 #define SIO_FBUF	SmakeFlag(1)	/* full buffering */
235 #define SIO_LBUF	SmakeFlag(2)	/* line buffering */
236 #define SIO_NBUF	SmakeFlag(3)	/* no buffering */
237 #define SIO_FEOF	SmakeFlag(4)	/* end-of-file */
238 #define SIO_FERR	SmakeFlag(5)	/* error ocurred */
239 #define SIO_USERBUF	SmakeFlag(6)	/* buffer is from user */
240 #define SIO_INPUT	SmakeFlag(7)	/* input stream */
241 #define SIO_OUTPUT	SmakeFlag(8)	/* output stream */
242 #define SIO_NOLINENO	SmakeFlag(9)	/* line no. info is void */
243 #define SIO_NOLINEPOS	SmakeFlag(10)	/* line pos is void */
244 #define SIO_STATIC	SmakeFlag(11)	/* Stream in static memory */
245 #define SIO_RECORDPOS	SmakeFlag(12)	/* Maintain position */
246 #define SIO_FILE	SmakeFlag(13)	/* Stream refers to an OS file */
247 #define SIO_NOERROR	SmakeFlag(14)	/* Ignore write errors */
248 #define SIO_NOFEOF	SmakeFlag(15)	/* don't set SIO_FEOF flag */
249 #define SIO_TEXT	SmakeFlag(16)	/* text-mode operation */
250 #define SIO_FEOF2	SmakeFlag(17)	/* attempt to read past eof */
251 #define SIO_FEOF2ERR	SmakeFlag(18)	/* Sfpasteof() */
252 #define SIO_NOCLOSE     SmakeFlag(19)	/* Do not close on abort */
253 #define SIO_APPEND	SmakeFlag(20)	/* opened in append-mode */
254 #define SIO_UPDATE	SmakeFlag(21)	/* opened in update-mode */
255 #define SIO_ISATTY	SmakeFlag(22)	/* Stream is a tty */
256 #define SIO_CLOSING	SmakeFlag(23)	/* We are closing the stream */
257 #define SIO_TIMEOUT	SmakeFlag(24)	/* We had a timeout */
258 #define SIO_NOMUTEX	SmakeFlag(25)	/* Do not allow multi-thread access */
259 #define SIO_ADVLOCK	SmakeFlag(26)	/* File locked with advisory lock */
260 #define SIO_WARN	SmakeFlag(27)	/* Pending warning */
261 #define SIO_RAW		SmakeFlag(28)	/* TTY Stream is in raw mode */
262 #define SIO_REPXML	SmakeFlag(29)	/* Bad char --> XML entity */
263 #define SIO_REPPL	SmakeFlag(30)	/* Bad char --> Prolog \hex\ */
264 #define SIO_BOM		SmakeFlag(31)	/* BOM was detected/written */
265 
266 #define	SIO_SEEK_SET	0	/* From beginning of file.  */
267 #define	SIO_SEEK_CUR	1	/* From current position.  */
268 #define	SIO_SEEK_END	2	/* From end of file.  */
269 
270 PL_EXPORT(IOSTREAM *)	S__getiob(void);	/* get DLL's __iob[] address */
271 
272 PL_EXPORT_DATA(IOFUNCTIONS)	Sfilefunctions;	/* OS file functions */
273 PL_EXPORT_DATA(int)		Slinesize;		/* Sgets() linesize */
274 #if defined(__CYGWIN__) && !defined(PL_KERNEL)
275 #define S__iob S__getiob()
276 #else
277 PL_EXPORT_DATA(IOSTREAM)	S__iob[3];		/* Libs standard streams */
278 #endif
279 
280 #define Sinput  (&S__iob[0])		/* Stream Sinput */
281 #define Soutput (&S__iob[1])		/* Stream Soutput */
282 #define Serror  (&S__iob[2])		/* Stream Serror */
283 
284 #define Sgetchar()	Sgetc(Sinput)
285 #define Sputchar(c)	Sputc((c), Soutput)
286 
287 #define S__updatefilepos_getc(s, c) \
288 	((s)->position ? S__fupdatefilepos_getc((s), (c)) \
289 		       : (c))
290 
291 #define Snpgetc(s) ((s)->bufp < (s)->limitp ? (int)(*(s)->bufp++)&0xff \
292 					    : S__fillbuf(s))
293 #define Sgetc(s) S__updatefilepos_getc((s), Snpgetc(s))
294 
295 /* Control-operations */
296 #define SIO_GETSIZE	(1)		/* get size of underlying object */
297 #define SIO_GETFILENO	(2)		/* get underlying file (if any) */
298 #define SIO_SETENCODING	(3)		/* modify encoding of stream */
299 #define SIO_FLUSHOUTPUT	(4)		/* flush output */
300 #define SIO_LASTERROR	(5)		/* string holding last error */
301 #ifdef __WINDOWS__
302 #define SIO_GETWINSOCK  (6)		/* get underlying SOCKET object */
303 #endif
304 #define SIO_GETPENDING	(7)		/* get #pending bytes */
305 
306 /* Sread_pending() */
307 #define SIO_RP_BLOCK 0x1		/* wait for new input */
308 #define SIO_RP_NOPOS 0x2		/* Do not update position */
309 
310 #if IOSTREAM_REPLACES_STDIO
311 
312 #undef FILE
313 #undef stdin
314 #undef stdout
315 #undef stderr
316 #undef putc
317 #undef getc
318 #undef putchar
319 #undef getchar
320 #undef feof
321 #undef ferror
322 #undef fileno
323 #undef clearerr
324 
325 #define FILE		IOSTREAM
326 #define stdin		Sinput
327 #define stdout		Soutput
328 #define stderr		Serror
329 
330 #define	putc		Sputc
331 #define	getc		Sgetc
332 #define	fputc		Sputc
333 #define	fgetc		Sgetc
334 #define getw		Sgetw
335 #define putw		Sputw
336 #define fread		Sfread
337 #define fwrite		Sfwrite
338 #define	ungetc		Sungetc
339 #define putchar		Sputchar
340 #define getchar		Sgetchar
341 #define feof		Sfeof
342 #define ferror		Sferror
343 #define clearerr	Sclearerr
344 #define	fflush		Sflush
345 #define	fseek		Sseek
346 #define	ftell		Stell
347 #define	fclose		Sclose
348 #define fgets		Sfgets
349 #define gets		Sgets
350 #define	fputs		Sfputs
351 #define	puts		Sputs
352 #define	fprintf		Sfprintf
353 #define	printf		Sprintf
354 #define	vprintf		Svprintf
355 #define	vfprintf	Svfprintf
356 #define	sprintf		Ssprintf
357 #define	vsprintf	Svsprintf
358 #define fopen		Sopen_file
359 #define fdopen		Sfdopen
360 #define	fileno		Sfileno
361 #define popen		Sopen_pipe
362 
363 #endif /*IOSTREAM_REPLACES_STDIO*/
364 
365 		 /*******************************
366 		 *	    PROTOTYPES		*
367 		 *******************************/
368 
369 PL_EXPORT(void)		SinitStreams();
370 PL_EXPORT(void)		Scleanup(void);
371 PL_EXPORT(void)		Sreset(void);
372 PL_EXPORT(int)		S__fupdatefilepos_getc(IOSTREAM *s, int c);
373 PL_EXPORT(int)		S__fillbuf(IOSTREAM *s);
374 PL_EXPORT(int)		Sset_timeout(IOSTREAM *s, int tmo);
375 PL_EXPORT(int)		Sunit_size(IOSTREAM *s);
376 					/* byte I/O */
377 PL_EXPORT(int)		Sputc(int c, IOSTREAM *s);
378 PL_EXPORT(int)		Sfgetc(IOSTREAM *s);
379 PL_EXPORT(int)		Sungetc(int c, IOSTREAM *s);
380 					/* multibyte I/O */
381 PL_EXPORT(int)		Scanrepresent(int c, IOSTREAM *s);
382 PL_EXPORT(int)		Sputcode(int c, IOSTREAM *s);
383 PL_EXPORT(int)		Sgetcode(IOSTREAM *s);
384 PL_EXPORT(int)		Speekcode(IOSTREAM *s);
385 					/* word I/O */
386 PL_EXPORT(int)		Sputw(int w, IOSTREAM *s);
387 PL_EXPORT(int)		Sgetw(IOSTREAM *s);
388 PL_EXPORT(size_t)	Sfread(void *data, size_t size, size_t elems,
389 			       IOSTREAM *s);
390 PL_EXPORT(size_t)	Sfwrite(const void *data, size_t size, size_t elems,
391 				IOSTREAM *s);
392 PL_EXPORT(int)		Sfeof(IOSTREAM *s);
393 PL_EXPORT(int)		Sfpasteof(IOSTREAM *s);
394 PL_EXPORT(int)		Sferror(IOSTREAM *s);
395 PL_EXPORT(void)		Sclearerr(IOSTREAM *s);
396 PL_EXPORT(int)		Sseterr(IOSTREAM *s, int which, const char *message);
397 PL_EXPORT(int)		Sset_exception(IOSTREAM *s, term_t ex);
398 PL_EXPORT(int)		Ssetenc(IOSTREAM *s, IOENC new_enc, IOENC *old_enc);
399 PL_EXPORT(int)		Ssetlocale(IOSTREAM *s,
400 				   struct PL_locale *new_loc,
401 				   struct PL_locale **old_loc);
402 PL_EXPORT(int)		Sflush(IOSTREAM *s);
403 PL_EXPORT(int64_t)	Ssize(IOSTREAM *s);
404 PL_EXPORT(int)		Sseek(IOSTREAM *s, long pos, int whence);
405 PL_EXPORT(long)		Stell(IOSTREAM *s);
406 PL_EXPORT(int)		Sclose(IOSTREAM *s);
407 PL_EXPORT(char *)	Sfgets(char *buf, int n, IOSTREAM *s);
408 PL_EXPORT(char *)	Sgets(char *buf);
409 PL_EXPORT(ssize_t)	Sread_pending(IOSTREAM *s,
410 				      char *buf, size_t limit, int flags);
411 PL_EXPORT(size_t)	Spending(IOSTREAM *s);
412 PL_EXPORT(int)		Sfputs(const char *q, IOSTREAM *s);
413 PL_EXPORT(int)		Sputs(const char *q);
414 PL_EXPORT(int)		Sfprintf(IOSTREAM *s, const char *fm, ...);
415 PL_EXPORT(int)		Sprintf(const char *fm, ...);
416 PL_EXPORT(int)		Svprintf(const char *fm, va_list args);
417 PL_EXPORT(int)		Svfprintf(IOSTREAM *s, const char *fm, va_list args);
418 PL_EXPORT(int)		Ssprintf(char *buf, const char *fm, ...);
419 PL_EXPORT(int)		Ssnprintf(char *buf, size_t size, const char *fm, ...);
420 PL_EXPORT(int)		Svsprintf(char *buf, const char *fm, va_list args);
421 PL_EXPORT(int)		Svsnprintf(char *buf, size_t size, const char *fm, va_list args);
422 PL_EXPORT(int)		Svdprintf(const char *fm, va_list args);
423 PL_EXPORT(int)		Sdprintf(const char *fm, ...);
424 PL_EXPORT(int)		Slock(IOSTREAM *s);
425 PL_EXPORT(int)		StryLock(IOSTREAM *s);
426 PL_EXPORT(int)		Sunlock(IOSTREAM *s);
427 PL_EXPORT(IOSTREAM *)	Snew(void *handle, int flags, IOFUNCTIONS *functions);
428 PL_EXPORT(IOSTREAM *)	Sopen_file(const char *path, const char *how);
429 PL_EXPORT(IOSTREAM *)	Sfdopen(int fd, const char *type);
430 PL_EXPORT(int)		Sfileno(IOSTREAM *s);
431 #ifdef __WINDOWS__
432 #if defined(_WINSOCKAPI_) || defined(NEEDS_SWINSOCK) /* have SOCKET */
433 PL_EXPORT(SOCKET)	Swinsock(IOSTREAM *s);
434 #endif
435 #endif
436 PL_EXPORT(IOSTREAM *)	Sopen_pipe(const char *command, const char *type);
437 PL_EXPORT(IOSTREAM *)	Sopenmem(char **buffer, size_t *sizep, const char *mode);
438 PL_EXPORT(IOSTREAM *)	Sopen_string(IOSTREAM *s, char *buf, size_t sz, const char *m);
439 PL_EXPORT(int)		Sclosehook(void (*hook)(IOSTREAM *s));
440 PL_EXPORT(void)		Sfree(void *ptr);
441 PL_EXPORT(int)		Sset_filter(IOSTREAM *parent, IOSTREAM *filter);
442 PL_EXPORT(void)		Ssetbuffer(IOSTREAM *s, char *buf, size_t size);
443 
444 PL_EXPORT(int64_t)	Stell64(IOSTREAM *s);
445 PL_EXPORT(int)		Sseek64(IOSTREAM *s, int64_t pos, int whence);
446 
447 PL_EXPORT(int)		ScheckBOM(IOSTREAM *s);
448 PL_EXPORT(int)		SwriteBOM(IOSTREAM *s);
449 
450 #ifdef __cplusplus
451 }
452 #endif
453 
454 #endif /*_PL_STREAM_H*/
455