/*
Copyright (c) 1993 Xerox Corporation.  All rights reserved.
*/
/*
$Id$

$Date$
 *
 */

#ifndef ←←PCR←EmuAstdioPvt←h
#define ←←PCR←EmuAstdioPvt←h

#include <th/PCR←Th.h>
#include <emu/PCR←EmuData.h>

#include <stdio.h>


/*
 * Global lock and list of all streams ...
 */

PCR←Th←ML PCR←Stdio←globalLock;

FILE * PCR←Stdio←streams;



/*
 * Common str←flags bits
 */

#define PCR←STDIO←READ		0x1
    /* stream may be used for input */
#define PCR←STDIO←WRITE		0x2
    /* stream may be used for output */


/*
 * Object methods:
 *
 * These may change only the str←{read,write}{Count,Ptr} fields.
 *
 * In particular, they should return error values, but not store
 *   then into str←status.
 *
 * Note if the str←{read,write}Count fields are maintained at 0,
 *   the macros will *always* call out-of-line.
 */

typedef PCR←ERes (PCR←Stdio←SetvbufProc)(FILE *stream);
/*
    Called after setvbuf to notify the underlying implementation.
*/

extern PCR←Stdio←SetvbufProc PCR←Stdio←NullSetvbufProc;
extern PCR←Stdio←SetvbufProc PCR←Stdio←ErrSetvbufProc;


typedef PCR←ERes (PCR←Stdio←ReadProc)(
        FILE *stream, char *buf, size←t nBytes,
        const PCR←sigset←t *sigMask, PCR←Msec wakeup );
/*
    Like read, with side-effect of reading ahead into buffers
      associated with stream.
    Return PCR←ERes←FromRes(nBytesRead) on success.
*/

extern PCR←Stdio←ReadProc PCR←Stdio←ErrReadProc;


typedef PCR←ERes (PCR←Stdio←WriteProc)(
        FILE *stream, const char *buf, size←t nBytes, PCR←Bool flush,
        const PCR←sigset←t *sigMask, PCR←Msec wakeup);
/*
    Like write, with side-effect of writing out buffers
      associated with stream.  If flush is PCR←Bool←true,
      then all buffered data must be written.
    Return PCR←ERes←FromRes(nBytes) on success.
*/

extern PCR←Stdio←WriteProc PCR←Stdio←ErrWriteProc;


typedef PCR←ERes (PCR←Stdio←PushBackProc)(
        FILE *stream, int c);
/*
    Push c back into read buffer, for ungetc implementation.
    Return PCR←ERes←okay on success.
*/

extern PCR←Stdio←PushBackProc PCR←Stdio←ErrPushBackProc;


typedef PCR←ERes (PCR←Stdio←SeekProc)(
        FILE *stream, fpos←t offset, int whence, fpos←t *where,
        const PCR←sigset←t *sigMask, PCR←Msec wakeup );
/*
    Flush any buffered data and seek the backing file if possible.
    If where is not NIL, return new position in *where.
*/

extern PCR←Stdio←SeekProc PCR←Stdio←ErrSeekProc;


typedef PCR←ERes (PCR←Stdio←CloseProc)(FILE *stream,
        const PCR←sigset←t *sigMask, PCR←Msec wakeup);
/*
    Called when the stream is closed (writeProc is also called on close,
    before closeProc).  CloseProc should take any client-specific closing
    actions,  such as closing the file corresponding to the stream or
    freeing the buffer space for the stream.  If it returns an error,
    (-1) will be returned from the fclose call.  If an error occurs while
    closing the stream, then the FILE structure should not be de-allocated,
    since the client will need to get at information in it to find out what
    went wrong.
*/

extern PCR←Stdio←CloseProc PCR←Stdio←NullCloseProc;



struct PCR←Stdio←StreamProcsRep {

    PCR←Stdio←SetvbufProc *strp←setvbufProc;
    PCR←Stdio←ReadProc *strp←readProc;
    PCR←Stdio←WriteProc *strp←writeProc;
    PCR←Stdio←PushBackProc *strp←pushBackProc;
    PCR←Stdio←SeekProc *strp←seekProc;
    PCR←Stdio←CloseProc *strp←closeProc;

};

typedef struct PCR←Stdio←StreamProcsRep PCR←Stdio←StreamProcs;

#define PCR←Stdio←GetStreamProc(s,name) \
	(*(((PCR←Stdio←StreamProcs *)((s)->str←procs))->strp←##name))


/*
 * Stream installation
 */

typedef PCR←ERes ((PCR←Stdio←InstallProc)(FILE *stream));


extern PCR←ERes
PCR←Stdio←InstallStream(
    FILE *stream,
    PCR←Bool readable,
    PCR←Bool writable,
    PCR←Stdio←StreamProcs *procs,
    PCR←Any clientData,
    PCR←Stdio←InstallProc *worker
);

extern void
PCR←Stdio←UninstallStreamInternal(
    FILE *stream
);


/*
 * Utilities
 */


extern FILE *
PCR←Stdio←StreamFromStdStream(FILE *std);
/*
    Convert a stream that might be stdin/stdout/stderr
      to an ordinary stream by looking up per-thread data.
*/


extern PCR←ERes 
PCR←Stdio←ParseMode(
    const char *mode,
    PCR←Bool *readable,
    PCR←Bool *writable,
    int *openFlags
);
/*
    Parse mode string (passed to fopen, ...)
*/



#endif /* !←←PCR←EmuAstdioPvt←h */
/*
$Log$
*/