/* BEGIN LICENSE BLOCK
 * Version: CMPL 1.1
 *
 * The contents of this file are subject to the Cisco-style Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file except
 * in compliance with the License.  You may obtain a copy of the License
 * at www.eclipse-clp.org/license.
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
 * the License for the specific language governing rights and limitations
 * under the License. 
 * 
 * The Original Code is  The ECLiPSe Constraint Logic Programming System. 
 * The Initial Developer of the Original Code is  Cisco Systems, Inc. 
 * Portions created by the Initial Developer are
 * Copyright (C) 1989-2006 Cisco Systems, Inc.  All Rights Reserved.
 * 
 * Contributor(s): ECRC GmbH
 * 
 * END LICENSE BLOCK */


/*
 * SEPIA INCLUDE FILE
 *
 * VERSION	$Id: ec_io.h,v 1.13 2017/09/01 03:05:09 jschimpf Exp $
 */

/*
 * IDENTIFICATION		io.h
 *
 * DESCRIPTION			Definitions concerning the I/O.
 *	
 * CONTENTS:
 *
 */

#define TTY_BUF_SIZE		128

#define NO_PROMPT		D_UNKNOWN
#define NO_BUF			((unsigned char *) 0)
#define NO_PROC			((pri *) 0)
#define NO_STREAM		((stream_id) 0)

#define EOB_MARK		0

#define StreamId(n)		(StreamDescriptors[n])	/* stream_id from int */
#define StreamNr(nst)		((nst)->nr)	/* int from stream_id */

#define StreamUnit(nst)		(nst)->unit
#define StreamMode(nst)		(nst)->mode
#define StreamWriteOptions(nst)	((write_options_t*)(nst)->write_options)
#define StreamType(nst)		((nst)->mode & STYPE)
#define StreamNref(nst)		(nst)->nref
#define StreamCnt(nst)		(nst)->cnt
#define StreamSize(nst)		(nst)->size
#define StreamBuf(nst)		(nst)->buf
#define StreamWBuf(nst)		(nst)->wbuf
#define StreamPtr(nst)		(nst)->ptr
#define StreamLexSize(nst)	(nst)->lex_size
#define StreamLexAux(nst)	(nst)->lex_aux
#define StreamLine(nst)		(nst)->line
#define StreamName(nst)		(nst)->name
#define StreamPath(nst)		(nst)->pathname
#define StreamOffset(nst)	(nst)->offset
#define StreamPrompt(nst)	(nst)->prompt
#define StreamEncoding(nst)	(nst)->encoding
#define StreamPromptStream(nst)	(nst)->prompt_stream
#define StreamPairedStream(nst)	(nst)->paired_stream
#define StreamEvent(nst)	(nst)->event
#define StreamEventEngine(nst)	(nst)->event_eng
#define StreamRand(nst)		(nst)->rand
#define StreamLastWritten(nst)	(nst)->last_written
#define StreamPastEof(nst)	((nst)->mode & MEOF)
#define StreamFILE(nst)		((FILE *) (nst)->stdfile)
#define StreamMethods(nst)	(* (io_channel_t *) (nst)->methods)
#define SetStreamMethods(nst,m)	(nst)->methods = (m);

#define StreamHandle(nst) \
	ecl_handle(ec_eng, &stream_tid, (t_ext_ptr)stream_tid.copy(nst))


/* some of the data is used for sockets differently */
#define SocketInputStream(nst)	StreamPairedStream(nst)
#define SocketUnix(nst)		StreamPrompt(nst)
#define SocketType(nst)		StreamLexSize(nst)
#define SocketConnection(nst)	StreamLexAux(nst)

#define StreamInputStream(nst)	(!IsReadStream(nst)? StreamPairedStream(nst): nst)

#define IsOpened(nst)		(StreamMode(nst) != SCLOSED)

#define IsNullStream(nst)	((StreamMode(nst) & STYPE) == SNULL)
#define IsTty(nst)		((StreamMode(nst) & STYPE) == STTY)
#define IsStringStream(nst)	((StreamMode(nst) & STYPE) == SSTRING)
#define IsQueueStream(nst)	((StreamMode(nst) & STYPE) == SQUEUE)
#define IsPipeStream(nst)	((StreamMode(nst) & STYPE) == SPIPE)
#define IsSocket(nst)		((StreamMode(nst) & STYPE) == SSOCKET)
#define IsInvalidSocket(nst)	((StreamMode(nst) & (STYPE | SREAD)) == (SSOCKET | SREAD))

#define IsFileStream(nst)	((StreamMode(nst) & STYPE) == SFILE)
#define IsReadStream(nst)	(StreamMode(nst) & SREAD)
#define IsWriteStream(nst)	(StreamMode(nst) & SWRITE)
#define IsReadWriteStream(nst)	((StreamMode(nst) & SRDWR) == SRDWR)
#define IsReadlineStream(nst)	(StreamMode(nst) & READLINE)

#define IsTextStream(nst)	(StreamEncoding(nst) > SENC_OCTET)

/* streams which can recover from being at eof */
#define IsSoftEofStream(nst)	((StreamMode(nst) & SEOF_ACTION) == SEOF_RESET)

#define SystemStream(nst)	(				\
				    (nst) == current_input_ ||	\
				    (nst) == current_output_ ||	\
				    (nst) == current_err_ ||	\
				    (nst) == warning_output_ ||	\
				    (nst) == log_output_ ||	\
				    (nst) == user_input_ ||	\
				    (nst) == user_output_ ||	\
				    (nst) == user_err_ ||	\
				    (nst) == null_		\
				)


/****
***** THIS IS PRIVATE TO THE I/O PART
***** BE CAREFUL IF YOU INTEND TO USE THIS
****/

#define BUFSIZE 	1024

#define NO_UNIT		(-1)

/* stream mode flags */
#define SCLOSED		0x0000	/* the channel is closed	*/
#define SREAD		0x0001	/* READ allowed			*/
#define SWRITE		0x0002	/* WRITE allowed		*/
#define SRDWR		0x0003
#define SAPPEND		0x0004	/* always with SWRITE, never with SREAD	*/
				/* only in SFILE streams	*/
#define SMODEBITS	0x0007

/* stream type field */
#define STYPE_SHIFT	3
#define STYPE_NUM	((STYPE>>STYPE_SHIFT)+1)
#define STYPE		0x0038	/* type mask			*/
#define SFILE		0x0000
#define SSTRING		0x0008
#define SPIPE		0x0010
#define SQUEUE		0x0018
#define SNULL		0x0020
#define SSOCKET		0x0028
#define STTY		0x0030
/* #define 		0x0038	*/

/* other stream properties */
#define SEOLCR		0x0040	/* output CR(+LF) at end of line */
#define SDONTCLOSE	0x0080	/* never close (stdin/out/err etc) */
#define DONT_PROMPT	0x0100	/* don't print the next prompt	*/
#define MREAD		0x0200	/* we have read a buffer	*/
#define MWRITE		0x0400	/* we wrote into the buffer	*/
#define MEOF		0x0800	/* eof has been read (past eof)	*/
#define SSCRAMBLE	0x1000	/* scramble stream data		*/
#define SYIELD		0x2000	/* queues only: yield on eof or flush */
#define REPROMPT_ONLY	0x4000	/* suppress initial prompts on this stream */
#define SFLUSHEOL	0x8000	/* flush stream at end-of-line	*/
#define SNONBLOCKING	0x10000	/* don't block if stream not ready */
#define SSIGIO		0x20000	/* SIGIO is enabled for this stream */
#define SNOMACROEXP	0x40000	/* suppress macro expansion	*/
#define SCOMPRESS	0x80000	/* try to compress output on this stream */
#define SSELECTABLE	0x100000 /* stream supports select/3 */
#define SNUMBERUSED	0x200000 /* stream may be referred to by number */
#define SDELETELOST	0x400000 /* delete file when stream handle is lost */
#define SDELETECLOSED	0x800000 /* delete file when stream is closed */
#define SREPOSITION	0x1000000 /* can be repositioned (seek) */

#define SEOF_ACTION	0x6000000 /* eof_action (ISO):			*/
#define SEOF_ERROR	0x0000000 /* treat past-eof as permission error	*/
#define SEOF_RESET	0x2000000 /* return eof code and allow repeat	*/
#define SEOF_CODE	0x4000000 /* return eof code (-1,end_of_file)	*/

#define SSLAVE		0x8000000 /* paired stream descriptor, only reachable */
				  /* from master (e.g. SSOCKET|SREAD)	*/


/* how many characters can be ungotten */
#define LOOKAHEAD		4

/* encodings (0 binary, >0 text) */
#define SENC_OCTET	0
#define SENC_ASCII	1
#define SENC_LATIN1	2
#define SENC_NUM	3
#define SENC_DEFAULT	SENC_LATIN1

/* options for ec_close_stream() */
#define CLOSE_FORCE	1
#define CLOSE_LOST	2

/*
 * action codes for io_rpc()
 */
#define IO_FLUSH	1
#define IO_FILL		2
#define IO_CLOSE	3
#define IO_TTYIN	4
#define IO_BIND		5
#define IO_CONNECT	6
#define IO_LISTEN	7
#define IO_ACCEPT	8

#define Lock_Stream(nst)	mt_mutex_lock(&nst->lock)
#define Unlock_Stream(nst)	mt_mutex_unlock(&nst->lock)

#define RemoteStream(nst) \
	(nst->fd_pid && nst->fd_pid != own_pid && nst->aport)


#define Trigger_Gc_If_Out_Of_Streams { \
        if (NbStreamsFree == 0) { Set_Tg_Soft_Lim(TG) } \
}


#ifdef _WIN32
#undef USE_REAL_SIGIO
#define StreamCanNotifyViaThread(nst) IsSocket(nst)
#else
/* can use real SIGIO in Unix, but no longer done by default */
/*#define USE_REAL_SIGIO*/
#define StreamCanNotifyViaThread(nst) (IsSocket(nst) || IsPipeStream(nst))
#endif

#ifdef USE_REAL_SIGIO
#define StreamNeedsThread(nst) \
	((StreamMode(nst) & SSIGIO) || !IsNil(StreamEvent(nst).tag))
#else
#define StreamNeedsThread(nst) \
	(!IsNil(StreamEvent(nst).tag))
#endif


/* defines for the output functions */

#define	CANONICAL		1	/* ignore operators		*/
#define	FULLDEPTH		2	/* ignore depth			*/
#define	DOTLIST			4	/* write lists in dot notation	*/
#define	QUOTED			8	/* print quotes when needed	*/
#define	VAR_NUMBERS	     0x10	/* print var number only	*/
#define	VAR_NAMENUM	     0x20	/* print var name (if any) and number */
#define	PRINT_CALL	     0x40	/* print was called, use portray */
#define	WRITE_COMPACT	     0x80	/* don't print unnecessary spaces */
#define	ATTRIBUTE	    0x100	/* print metaterm attribute	*/
#define	WRITE_GOAL	    0x200	/* printed term is a goal	*/
#define	STD_ATTR	    0x400	/* attribute in standard form	*/
#define	NO_MACROS	    0x800	/* don't apply write macros	*/
#define	WRITE_CLAUSE	   0x1000	/* printed term is a clause	*/
#define	DONT_QUOTE_NL	   0x2000	/* print newlines even when quoted */
#define	VAR_ANON	   0x4000	/* print variables as _		*/
#define	OUT_DOLLAR_VAR	   0x8000	/* print $VAR(I) as variables	*/
#define	PORTRAY_VAR	  0x10000	/* call portray even for variables */
#define	TERM_FULLSTOP	  0x20000	/* terminate term with a fullstop */
#define	TERM_NEWLINE	  0x40000	/* terminate term with a newline */
#define	OUTPUT_MODE_CHARS      19       /* the above have chars in printf */

#define	TERM_FLUSH	  0x80000	/* flush after term was printed */
#define	TERM_CONTINUE	 0x100000	/* separate from preceding token */
#define	PORTRAY2	 0x200000	/* a portray/2 predicate exists	*/
#define	PORTRAY1	 0x400000	/* a portray/1 predicate exists	*/
#define	VARTERM		 0x800000	/* print variables as '_'(...)	*/
#define	TERM_NOPSPC	0x1000000	/* no space around operators	*/
#define	TERM_NOBRACES	0x2000000	/* disable {_} notation for {}/1 */
#define	TERM_CYCLES	0x4000000	/* check for, and print cycles  */
#define	TERM_CYCERR	0x8000000	/* cycles are error             */
#define	TERM_COMMAOP   0x10000000	/* always obey ,/2 operator     */

#define	OUTPUT_MODE_ALL   0xFFFFFFFF	/* all flag bits                */


#define DEFAULT_FLOAT_PRECISION 15      /* decimal digits */


/*
 * Types
 */

typedef struct {
    int		io_type;
    int		mode_defaults;
    int		buf_size_hint;
    int		(*close)(int);
    int		(*ready)();
    int		(*read)(int,char*,int,int*);
    int		(*write)(int,char*,int);
    int		(*at)(stream_id nst, long int*);
    int		(*at_eof)(stream_id);
    int		(*buffer_nonempty)(stream_id);
    int		(*truncate)();
    int		(*seek)(stream_id,long,int);
    int		(*flush)(stream_id);
    int		(*size)(stream_id);
    int		(*content)(stream_id,char*);
    int		(*outf)(stream_id,char*,int);
} io_channel_t;


/*
 * EXTERNAL VARIABLE DECLARATIONS: 
 */

Extern int		own_pid;
Extern void		my_io_aport();

Extern	int	ec_pwrite(ec_eng_t*,int,int,stream_id,value,type,const write_options_t*,dident,type);
Extern	int	ec_tty_in(stream_id);
Extern	int	ec_tty_out(stream_id, int);
Extern	int	ec_tty_outs(stream_id, char*, int);
Extern	int	ec_seek_stream(stream_id,long,int);
Extern	int	ec_stream_at(stream_id,long*);
Extern	int	ec_close_stream(stream_id, int);
Extern	int	ec_outfw(stream_id, word);
Extern	int	ec_outfc(stream_id, int);
Extern	int	ec_getch(stream_id);
Extern	int	ec_ungetch(stream_id);

Extern	int	fill_buffer(stream_id);
Extern	int	io_flush_out(stream_id);
Extern	int	set_sigio(int);
Extern	int	reset_sigio(int);
Extern	int	ec_stream_set_sigio(stream_id);
Extern	int	ec_stream_reset_sigio(stream_id);
Extern	int	ec_setup_stream_sigio_thread(stream_id);
Extern	int	ec_teardown_stream_sigio_thread(stream_id,int);
Extern	int	ec_reenable_sigio(stream_id, int, int);
Extern	void	mark_dids_from_streams(void);
Extern stream_id find_free_stream(void);
Extern stream_id alloc_slave_stream(void);
Extern void	init_stream(stream_id,int unit,int mode,dident name,
			stream_id pstream, int size);
Extern stream_id ec_open_file(char*,int,int*);
Extern stream_id get_stream_id(value,type,int,int,ec_eng_t*,int*);
Extern char	*ec_getstring(stream_id,word,word*);
Extern 	int	set_stream(dident, stream_id);
Extern	void	flush_and_close_io(int);
Extern	void	reset_ttys_and_buffers(void);

Extern t_ext_type stream_tid;
Extern t_ext_type write_options_tid;

Extern const write_options_t ec_write_options_default_;
Extern  void	ec_get_output_mode_string(write_options_t *wopts, char *s);
