1 /*  $Id$
2 
3     Part of SWI-Prolog
4 
5     Author:        Jan Wielemaker
6     E-mail:        jan@science.uva.nl
7     WWW:           http://www.swi-prolog.org
8     Copyright (C): 1985-2005, University of Amsterdam
9 
10     This library is free software; you can redistribute it and/or
11     modify it under the terms of the GNU Lesser General Public
12     License as published by the Free Software Foundation; either
13     version 2.1 of the License, or (at your option) any later version.
14 
15     This library is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18     Lesser General Public License for more details.
19 
20     You should have received a copy of the GNU Lesser General Public
21     License along with this library; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24 
25 #ifndef _PL_STREAM_H
26 #define _PL_STREAM_H
27 
28 /* This appears to make the wide-character support compile and work
29    on HPUX 11.23.  There really should be a cleaner way ...
30 */
31 #if defined(__hpux)
32 #include <sys/_mbstate_t.h>
33 #endif
34 
35 #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(__WINDOWS__)
36 #define __WINDOWS__ 1
37 #endif
38 
39 #include <stdarg.h>
40 #include <wchar.h>
41 #include <stddef.h>
42 #if defined(__WINDOWS__) && !defined(__MINGW32__)
43 typedef __int64 int64_t;
44 #if (_MSC_VER < 1300)
45 typedef long intptr_t;
46 typedef unsigned long uintptr_t;
47 #endif
48 typedef intptr_t ssize_t;		/* signed version of size_t */
49 #else
50 #include <unistd.h>
51 #include <inttypes.h>			/* more portable than stdint.h */
52 #endif
53 
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57 
58 		 /*******************************
59 		 *	       EXPORT		*
60 		 *******************************/
61 
62 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63 See SWI-Prolog.h, containing the same code   for  an explanation on this
64 stuff.
65 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
66 
67 #ifndef _PL_EXPORT_DONE
68 #define _PL_EXPORT_DONE
69 
70 #if (defined(__WINDOWS__) || defined(__CYGWIN__)) && !defined(__LCC__)
71 #define HAVE_DECLSPEC
72 #endif
73 
74 #ifdef HAVE_DECLSPEC
75 # ifdef PL_KERNEL
76 #define PL_EXPORT(type)		__declspec(dllexport) type
77 #define PL_EXPORT_DATA(type)	__declspec(dllexport) type
78 #define install_t	 	void
79 # else
80 #  ifdef __BORLANDC__
81 #define PL_EXPORT(type)	 	type _stdcall
82 #define PL_EXPORT_DATA(type)	extern type
83 #  else
84 #define PL_EXPORT(type)	 	extern type
85 #define PL_EXPORT_DATA(type)	__declspec(dllimport) type
86 #  endif
87 #define install_t	 	__declspec(dllexport) void
88 # endif
89 #else /*HAVE_DECLSPEC*/
90 #define PL_EXPORT(type)	 	extern type
91 #define PL_EXPORT_DATA(type)	extern type
92 #define install_t	 	void
93 #endif /*HAVE_DECLSPEC*/
94 #endif /*_PL_EXPORT_DONE*/
95 
96 		 /*******************************
97 		 *	    CONSTANTS		*
98 		 *******************************/
99 
100 #ifndef EOF
101 #define EOF (-1)
102 #endif
103 
104 #ifndef NULL
105 #define NULL ((void *)0)
106 #endif
107 
108 #if defined(__WINDOWS__) && !defined(EWOULDBLOCK)
109 #define EWOULDBLOCK	1000		/* Needed for socket handling */
110 #endif
111 #define EPLEXCEPTION	1001		/* errno: pending Prolog exception */
112 
113 #define SIO_BUFSIZE	(4096)		/* buffering buffer-size */
114 #define SIO_LINESIZE	(1024)		/* Sgets() default buffer size */
115 #define SIO_MAGIC	(7212676)	/* magic number */
116 #define SIO_CMAGIC	(42)		/* we are close (and thus illegal!) */
117 
118 typedef ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize);
119 typedef ssize_t (*Swrite_function)(void *handle, char*buf, size_t bufsize);
120 typedef long  (*Sseek_function)(void *handle, long pos, int whence);
121 typedef int64_t (*Sseek64_function)(void *handle, int64_t pos, int whence);
122 typedef int   (*Sclose_function)(void *handle);
123 typedef int   (*Scontrol_function)(void *handle, int action, void *arg);
124 
125 #if defined(O_PLMT) && defined(PL_KERNEL)
126 #include "pl-mutex.h"
127 #define IOLOCK recursiveMutex
128 #else
129 typedef void *		IOLOCK;		/* Definition for external use */
130 #endif
131 
132 typedef struct io_functions
133 { Sread_function	read;		/* fill the buffer */
134   Swrite_function	write;		/* empty the buffer */
135   Sseek_function	seek;		/* seek to position */
136   Sclose_function	close;		/* close stream */
137   Scontrol_function	control;	/* Info/control */
138   Sseek64_function	seek64;		/* seek to position (intptr_t files) */
139 } IOFUNCTIONS;
140 
141 typedef struct io_position
142 { int64_t		byteno;		/* byte-position in file */
143   int64_t		charno;		/* character position in file */
144   int			lineno;		/* lineno in file */
145   int			linepos;	/* position in line */
146   intptr_t		reserved[2];	/* future extensions */
147 } IOPOS;
148 
149 					/* NOTE: check with encoding_names */
150 					/* in pl-file.c */
151 typedef enum
152 { ENC_UNKNOWN = 0,			/* invalid/unknown */
153   ENC_OCTET,				/* raw 8 bit input */
154   ENC_ASCII,				/* US-ASCII (0..127) */
155   ENC_ISO_LATIN_1,			/* ISO Latin-1 (0..256) */
156   ENC_ANSI,				/* default (multibyte) codepage */
157   ENC_UTF8,
158   ENC_UNICODE_BE,			/* big endian unicode file */
159   ENC_UNICODE_LE,			/* little endian unicode file */
160   ENC_WCHAR				/* pl_wchar_t */
161 } IOENC;
162 
163 #define SIO_NL_POSIX  0			/* newline as \n */
164 #define SIO_NL_DOS    1			/* newline as \r\n */
165 #define SIO_NL_DETECT 3			/* detect processing mode */
166 
167 typedef struct io_stream
168 { char		       *bufp;		/* `here' */
169   char		       *limitp;		/* read/write limit */
170   char		       *buffer;		/* the buffer */
171   char		       *unbuffer;	/* Sungetc buffer */
172   int			lastc;		/* last character written */
173   int			magic;		/* magic number SIO_MAGIC */
174   int  			bufsize;	/* size of the buffer */
175   int			flags;		/* Status flags */
176   IOPOS			posbuf;		/* location in file */
177   IOPOS *		position;	/* pointer to above */
178   void		       *handle;		/* function's handle */
179   IOFUNCTIONS	       *functions;	/* open/close/read/write/seek */
180   int		        locks;		/* lock/unlock count */
181   IOLOCK *		mutex;		/* stream mutex */
182 					/* SWI-Prolog 4.0.7 */
183   void			(*close_hook)(void* closure);
184   void *		closure;
185 					/* SWI-Prolog 5.1.3 */
186   int			timeout;	/* timeout (milliseconds) */
187 					/* SWI-Prolog 5.4.4 */
188   char *		message;	/* error/warning message */
189   IOENC			encoding;	/* character encoding used */
190   struct io_stream *	tee;		/* copy data to this stream */
191   mbstate_t *		mbstate;	/* ENC_ANSI decoding */
192   struct io_stream *	upstream;	/* stream providing our input */
193   struct io_stream *	downstream;	/* stream providing our output */
194   unsigned		newline : 2;	/* Newline mode */
195   void *		exception;	/* pending exception (record_t) */
196   intptr_t		reserved[2];	/* reserved for extension */
197 } IOSTREAM;
198 
199 
200 #define SmakeFlag(n)	(1<<(n-1))
201 
202 #define SIO_FBUF	SmakeFlag(1)	/* full buffering */
203 #define SIO_LBUF	SmakeFlag(2)	/* line buffering */
204 #define SIO_NBUF	SmakeFlag(3)	/* no buffering */
205 #define SIO_FEOF	SmakeFlag(4)	/* end-of-file */
206 #define SIO_FERR	SmakeFlag(5)	/* error ocurred */
207 #define SIO_USERBUF	SmakeFlag(6)	/* buffer is from user */
208 #define SIO_INPUT	SmakeFlag(7)	/* input stream */
209 #define SIO_OUTPUT	SmakeFlag(8)	/* output stream */
210 #define SIO_NOLINENO	SmakeFlag(9)	/* line no. info is void */
211 #define SIO_NOLINEPOS	SmakeFlag(10)	/* line pos is void */
212 #define SIO_STATIC	SmakeFlag(11)	/* Stream in static memory */
213 #define SIO_RECORDPOS	SmakeFlag(12)	/* Maintain position */
214 #define SIO_FILE	SmakeFlag(13)	/* Stream refers to an OS file */
215 #define SIO_PIPE	SmakeFlag(14)	/* Stream refers to an OS pipe */
216 #define SIO_NOFEOF	SmakeFlag(15)	/* don't set SIO_FEOF flag */
217 #define SIO_TEXT	SmakeFlag(16)	/* text-mode operation */
218 #define SIO_FEOF2	SmakeFlag(17)	/* attempt to read past eof */
219 #define SIO_FEOF2ERR	SmakeFlag(18)	/* Sfpasteof() */
220 #define SIO_NOCLOSE     SmakeFlag(19)	/* Do not close on abort */
221 #define SIO_APPEND	SmakeFlag(20)	/* opened in append-mode */
222 #define SIO_UPDATE	SmakeFlag(21)	/* opened in update-mode */
223 #define SIO_ISATTY	SmakeFlag(22)	/* Stream is a tty */
224 #define SIO_CLOSING	SmakeFlag(23)	/* We are closing the stream */
225 #define SIO_TIMEOUT	SmakeFlag(24)	/* We had a timeout */
226 #define SIO_NOMUTEX	SmakeFlag(25)	/* Do not allow multi-thread access */
227 #define SIO_ADVLOCK	SmakeFlag(26)	/* File locked with advisory lock */
228 #define SIO_WARN	SmakeFlag(27)	/* Pending warning */
229 #define SIO_CLEARERR	SmakeFlag(28)	/* Clear error after reporting */
230 #define SIO_REPXML	SmakeFlag(29)	/* Bad char --> XML entity */
231 #define SIO_REPPL	SmakeFlag(30)	/* Bad char --> Prolog \hex\ */
232 #define SIO_BOM		SmakeFlag(31)	/* BOM was detected/written */
233 
234 #define	SIO_SEEK_SET	0	/* From beginning of file.  */
235 #define	SIO_SEEK_CUR	1	/* From current position.  */
236 #define	SIO_SEEK_END	2	/* From end of file.  */
237 
238 PL_EXPORT(IOSTREAM *)	S__getiob(void);	/* get DLL's __iob[] address */
239 
240 PL_EXPORT_DATA(IOFUNCTIONS)  Sfilefunctions;	/* OS file functions */
241 PL_EXPORT_DATA(int)	     Slinesize;		/* Sgets() linesize */
242 #if defined(__CYGWIN__) && !defined(PL_KERNEL)
243 #define S__iob S__getiob()
244 #else
245 PL_EXPORT_DATA(IOSTREAM)    S__iob[3];		/* Libs standard streams */
246 #endif
247 
248 #define Sinput  (&S__iob[0])		/* Stream Sinput */
249 #define Soutput (&S__iob[1])		/* Stream Soutput */
250 #define Serror  (&S__iob[2])		/* Stream Serror */
251 
252 #define Sgetchar()	Sgetc(Sinput)
253 #define Sputchar(c)	Sputc((c), Soutput)
254 
255 #define S__checkpasteeof(s,c) \
256 	if ( (c)==-1 && (s)->flags & (SIO_FEOF|SIO_FERR) ) \
257 	  ((s)->flags |= SIO_FEOF2)
258 #define S__updatefilepos_getc(s, c) \
259 	((s)->position ? S__fupdatefilepos_getc((s), (c)) \
260 		       : S__fcheckpasteeof((s), (c)))
261 
262 #define Snpgetc(s) ((s)->bufp < (s)->limitp ? (int)(*(s)->bufp++)&0xff \
263 					    : S__fillbuf(s))
264 #define Sgetc(s) S__updatefilepos_getc((s), Snpgetc(s))
265 
266 /* Control-operations */
267 #define SIO_GETSIZE	(1)		/* get size of underlying object */
268 #define SIO_GETFILENO	(2)		/* get underlying file (if any) */
269 #define SIO_SETENCODING	(3)		/* modify encoding of stream */
270 #define SIO_FLUSHOUTPUT	(4)		/* flush output */
271 #define SIO_LASTERROR	(5)		/* string holding last error */
272 
273 /* Sread_pending() */
274 #define SIO_RP_BLOCK 0x1		/* wait for new input */
275 
276 #if IOSTREAM_REPLACES_STDIO
277 
278 #undef FILE
279 #undef stdin
280 #undef stdout
281 #undef stderr
282 #undef putc
283 #undef getc
284 #undef putchar
285 #undef getchar
286 #undef feof
287 #undef ferror
288 #undef fileno
289 #undef clearerr
290 
291 #define FILE		IOSTREAM
292 #define stdin		Sinput
293 #define stdout		Soutput
294 #define stderr		Serror
295 
296 #define	putc		Sputc
297 #define	getc		Sgetc
298 #define	fputc		Sputc
299 #define	fgetc		Sgetc
300 #define getw		Sgetw
301 #define putw		Sputw
302 #define fread		Sfread
303 #define fwrite		Sfwrite
304 #define	ungetc		Sungetc
305 #define putchar		Sputchar
306 #define getchar		Sgetchar
307 #define feof		Sfeof
308 #define ferror		Sferror
309 #define clearerr	Sclearerr
310 #define	fflush		Sflush
311 #define	fseek		Sseek
312 #define	ftell		Stell
313 #define	fclose		Sclose
314 #define fgets		Sfgets
315 #define gets		Sgets
316 #define	fputs		Sfputs
317 #define	puts		Sputs
318 #define	fprintf		Sfprintf
319 #define	printf		Sprintf
320 #define	vprintf		Svprintf
321 #define	vfprintf	Svfprintf
322 #define	sprintf		Ssprintf
323 #define	vsprintf	Svsprintf
324 #define fopen		Sopen_file
325 #define fdopen		Sfdopen
326 #define	fileno		Sfileno
327 #define popen		Sopen_pipe
328 
329 #endif /*IOSTREAM_REPLACES_STDIO*/
330 
331 		 /*******************************
332 		 *	    PROTOTYPES		*
333 		 *******************************/
334 
335 PL_EXPORT(void)		SinitStreams(void);
336 PL_EXPORT(void)		Scleanup(void);
337 PL_EXPORT(void)		Sreset(void);
338 PL_EXPORT(int)		S__fupdatefilepos_getc(IOSTREAM *s, int c);
339 PL_EXPORT(int)		S__fcheckpasteeof(IOSTREAM *s, int c);
340 PL_EXPORT(int)		S__fillbuf(IOSTREAM *s);
341 PL_EXPORT(int)		Sunit_size(IOSTREAM *s);
342 					/* byte I/O */
343 PL_EXPORT(int)		Sputc(int c, IOSTREAM *s);
344 PL_EXPORT(int)		Sfgetc(IOSTREAM *s);
345 PL_EXPORT(int)		Sungetc(int c, IOSTREAM *s);
346 					/* multibyte I/O */
347 PL_EXPORT(int)		Scanrepresent(int c, IOSTREAM *s);
348 PL_EXPORT(int)		Sputcode(int c, IOSTREAM *s);
349 PL_EXPORT(int)		Sgetcode(IOSTREAM *s);
350 PL_EXPORT(int)		Sungetcode(int c, IOSTREAM *s);
351 					/* word I/O */
352 PL_EXPORT(int)		Sputw(int w, IOSTREAM *s);
353 PL_EXPORT(int)		Sgetw(IOSTREAM *s);
354 PL_EXPORT(size_t)	Sfread(void *data, size_t size, size_t elems,
355 			       IOSTREAM *s);
356 PL_EXPORT(size_t)	Sfwrite(const void *data, size_t size, size_t elems,
357 				IOSTREAM *s);
358 PL_EXPORT(int)		Sfeof(IOSTREAM *s);
359 PL_EXPORT(int)		Sfpasteof(IOSTREAM *s);
360 PL_EXPORT(int)		Sferror(IOSTREAM *s);
361 PL_EXPORT(void)		Sclearerr(IOSTREAM *s);
362 PL_EXPORT(void)		Sseterr(IOSTREAM *s, int which, const char *message);
363 #ifdef _FLI_H_INCLUDED
364 PL_EXPORT(void)		Sset_exception(IOSTREAM *s, term_t ex);
365 #else
366 PL_EXPORT(void)		Sset_exception(IOSTREAM *s, intptr_t ex);
367 #endif
368 PL_EXPORT(int)		Ssetenc(IOSTREAM *s, IOENC new_enc, IOENC *old_enc);
369 PL_EXPORT(int)		Sflush(IOSTREAM *s);
370 PL_EXPORT(long)		Ssize(IOSTREAM *s);
371 PL_EXPORT(int)		Sseek(IOSTREAM *s, long pos, int whence);
372 PL_EXPORT(long)		Stell(IOSTREAM *s);
373 PL_EXPORT(int)		Sclose(IOSTREAM *s);
374 PL_EXPORT(char *)	Sfgets(char *buf, int n, IOSTREAM *s);
375 PL_EXPORT(char *)	Sgets(char *buf);
376 PL_EXPORT(ssize_t)	Sread_pending(IOSTREAM *s,
377 				      char *buf, size_t limit, int flags);
378 PL_EXPORT(int)		Sfputs(const char *q, IOSTREAM *s);
379 PL_EXPORT(int)		Sputs(const char *q);
380 PL_EXPORT(int)		Sfprintf(IOSTREAM *s, const char *fm, ...);
381 PL_EXPORT(int)		Sprintf(const char *fm, ...);
382 PL_EXPORT(int)		Svprintf(const char *fm, va_list args);
383 PL_EXPORT(int)		Svfprintf(IOSTREAM *s, const char *fm, va_list args);
384 PL_EXPORT(int)		Ssprintf(char *buf, const char *fm, ...);
385 PL_EXPORT(int)		Svsprintf(char *buf, const char *fm, va_list args);
386 PL_EXPORT(int)		Svdprintf(const char *fm, va_list args);
387 PL_EXPORT(int)		Sdprintf(const char *fm, ...);
388 PL_EXPORT(int)		Slock(IOSTREAM *s);
389 PL_EXPORT(int)		StryLock(IOSTREAM *s);
390 PL_EXPORT(int)		Sunlock(IOSTREAM *s);
391 PL_EXPORT(IOSTREAM *)	Snew(void *handle, int flags, IOFUNCTIONS *functions);
392 PL_EXPORT(IOSTREAM *)	Sopen_file(const char *path, const char *how);
393 PL_EXPORT(IOSTREAM *)	Sfdopen(int fd, const char *type);
394 PL_EXPORT(int)	   	Sfileno(IOSTREAM *s);
395 PL_EXPORT(IOSTREAM *)	Sopen_pipe(const char *command, const char *type);
396 PL_EXPORT(IOSTREAM *)	Sopenmem(char **buffer, size_t *sizep, const char *mode);
397 PL_EXPORT(IOSTREAM *)	Sopen_string(IOSTREAM *s, char *buf, size_t sz, const char *m);
398 PL_EXPORT(int)		Sclosehook(void (*hook)(IOSTREAM *s));
399 PL_EXPORT(void)		Sfree(void *ptr);
400 PL_EXPORT(int)		Sset_filter(IOSTREAM *parent, IOSTREAM *filter);
401 PL_EXPORT(void)		Ssetbuffer(IOSTREAM *s, char *buf, size_t size);
402 
403 PL_EXPORT(int64_t)	Stell64(IOSTREAM *s);
404 PL_EXPORT(int)		Sseek64(IOSTREAM *s, int64_t pos, int whence);
405 
406 PL_EXPORT(int)		ScheckBOM(IOSTREAM *s);
407 PL_EXPORT(int)		SwriteBOM(IOSTREAM *s);
408 
409 #ifdef __cplusplus
410 }
411 #endif
412 
413 #endif /*_PL_STREAM_H*/
414