/*      @(#)io_stream.h 20.14 93/06/28 SMI      */

/*
 *  (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
 *  pending in the U.S. and foreign countries. See LEGAL NOTICE
 *  file for terms of the license.
 */

#ifndef suntool_io_stream_DEFINED
#define suntool_io_stream_DEFINED
#include <xview/sun.h>

#ifndef makedev
#include <sys/types.h>
#endif

/* TYPES */

struct  input_ops_vector
{
    int (*str_getc)(); /* (struct Stream *in)
                 * Note: it is the responsibility of the
                 * implementor of the stream to return EOF
                 * to indicate that the stream is empty,
                 * and to insure that subsequent attempts
                 * to read from that stream will continue
                 * to return EOF.
                 */
    int (*ungetc)();   /* (char c, struct Stream *in)
                 * implementor only responsible for
                 * for putting back characters that were there.
                 * should return EOF if was unable to put back
                 * the character.
                 * Note: if not provided by implementor,
                 * i.e., ungetc = NULL, will be supplied
                 * by stream package first time it is required.
*** NOT IMPLEMENTED YET ***
                 * See comment regarding ungetc below.
                 */
    char    *(*str_fgets)();/* (char *, n, struct Stream *in)
                 * reads n-1 characters, or up to a newline
                 * character, whichever comes first,
                 * from the stream in into the string s.
                 * The last character read into s is
                 * followed by a null character.
                 * The newline is included.                      * returns NULL on end of file or error.
                 * not every stream will implement this
                 * procedure. For those that don't, the
                 * equivalent n calls to str_getc will be
                 * performed.
                 */
    int (*chars_avail)();  /* (struct Stream *in) */
    struct posrec(*get_pos)();    /* (struct Stream *in)
                 * returns postion record consisting of
                 * line number and character position,
                 * character position is how many characters have been read.
                 * this is the value to give to set_pos
                 * if lineno = -1, means stream doesn't know
                 * lineno. This can occur after having
                 * reset with set_pos
                 */
    int (*set_pos)();  /* (int n, struct Stream *in)
                 * not every input stream will implement this
                 * procedure. returns -1 if not implemented
                 * or some other failure.
                 */

    void (*close)();        /* (struct Stream *in) */
};

struct  output_ops_vector
{
    int (*str_putc)();  /* (char c, struct Stream *out) */
    void (*str_fputs)();    /* (char *, struct Stream *out)
                 * copies the null-terminated string s to out.
                 * does not append a newline
                 */
    struct posrec(*get_pos)();      /* (struct Stream *out) */
    void (*flush)();    /* (struct Stream *out)
                 * can be defaulted to NULL = NOP
                 */
    void (*close)();        /* (struct Stream *stream) */
};

union   Ops_Pointer
{
    struct input_ops_vector     *input_ops;
    struct output_ops_vector    *output_ops;
};

enum Stream_Type {Input, Output};

struct  Stream
{
    enum Stream_Type    stream_type;
    char            *stream_class; /* e.g. "String_Input_Stream" */
    union Ops_Pointer   ops; /* the procedures that implement the stream */
    struct Stream
            *backing_stream;    /* for streams that are composed by layering one stream on top of the other, such as xv_filtered_comments_stream. Allows clients to get at the lower stream, e.g. to find out how many characters were seen at that level */
    caddr_t         client_data;
};

struct  posrec
{
    int     lineno;
    int     charpos;
};

typedef struct Stream STREAM;

/* GENERIC INPUT FUNCTIONS */

int stream_getc();
/* int stream_getc(in)
 *  STREAM  *in;
 * int so can return EOF
 */

int stream_ungetc();
/* int stream_ungetc(c, in)
 *  STREAM  *in;
 *  char        c;
 * if stream does not implement ungetc, first time ungetc is called
 * the stream will be redefined to be a layered stream which knows
 * how to implement ungetc. This will also occur if client tries
 * to put back a character  other than the one that was just read
 * and stream is unprepared to deal with
 * this, e.g. a file stream.
 */

int stream_peekc();
/* int stream_peekc(in)
 *  struct Stream   *in;
 * returns next character in stream without consuming it, i.e., the
 * next call to getc or peekc will see the same character
 * int so can return EOF. uses ungetc
 */

char *stream_gets();
/* char *stream_gets(s, in)
 *  char         *s;
 *  STREAM  *in;
 * analagous to gets:
 * reads characters from in until newline is read.
 * Terminating newline character is not stored in s, and s is terminated
 * with null character
  * newlines preceded by \  are treated the same as any other character, i.e.
 * both the \ and the newline are copied into s.
 * if an error occurs, or if no characters are read, the value NULL is returned
 */

char *stream_fgets();
/* char *stream_fgets(s, n, in)
 *  char         *s;
 *  int n;
 *  struct Stream   *in;
 * analagous to fgets, i.e., like stream_gets, except newline is included
 */

int stream_chars_avail();
/* int chars_avail(in)
 *  struct Stream   *in;
 */

void stream_ungetstr();
/* stream_ungetstr(s, in)
 *  char        *s;
 *  struct Stream   *in;

*** NOT IMPLEMENTED YET ***
Implements "stuffing" of a sequence of characters.
redefines in so that the next n characters it returns are those in s.
Then in returns to its normal state. For a similar operation
involving another stream, see append_streams below.
*/

void append_streams();
/* append_streams(in1, in2)
 *  struct Stream   in1, in2;
 *
*** NOT IMPLEMENTED YET ***
 * redefines in2 so that characters are read from in1 until it returns EOF,
 * then in2 is returned to its normal state, i.e. subsequent calls
 * to getc will return characters from in2.
 */

int stream_set_pos();
/* int stream_position(n, stream)
 *  int n;
 *  STREAM  *stream;
 * positions stream so that next character read will be the nth character.
 */

#ifndef CHARCLASS    /* also defined in io_streams.h */
#define CHARCLASS
enum CharClass {Break, Sepr, Other};
#endif

char *stream_get_token();
/* char *stream_get_token (in, dest, charproc)
 *  struct Stream   *in;
 *  char *dest;
 *  enum CharClass (*charproc) ();

 * stream_get_token is used for tokenizing input, where more degree of
 * flexibility is required than simply delimiting tokens by white spaces
 * characters are divided into three classes, Break, Sepr, and Other.
 * separators (Sepr) serve to delimit a token. Leading separators are skipped.
 * think of separators as white space. Break characters delimit tokens, and
 * are themselves tokens. Thus, if a break character is the first thing seen
 * it is returned as the token. If any non-separator characters have been seen,
 * then they are returned as the token, and the break character will be the
 * returned as the result of the next call to get_token.
 * for example, if charproc returns Sepr for space, and Break for '(' and ')'
 * and Other for all alphabetic characters, then the string "now (is) the"
 * will yield five tokens consisting of "now" "(" "is" ")" and "the"

 * get_token stores the token that it constructs into dest,
 * which is also returned as its value.

 * get_token returns NULL, rather than the empty string, corresponding to
 * the case where the token is empty
 */

void xv_skip_over();
/* xv_skip_over(in, charproc)
 *  struct Stream   *in;
 *  enum CharClass (*charproc) ();
 * reads and discards all characters from in for which charproc
 * returns sepr.
 * e.g. xv_skip_over(in, xv_white_space) skips over all white space
 */

#ifndef WHITESPACE
#define WHITESPACE
extern enum CharClass xv_white_space();
/* returns sepr for blanks, newlines, and tabs, other for everything else */
#endif

#ifndef CHARACTION   /* also defined in io_streams.h */
#define CHARACTION
struct CharAction
{
    Bool    stop;
    Bool    include;
};
#endif

char *stream_get_sequence();
/* char *stream_get_sequence (in, dest, charproc);
 *  struct Stream   *in;
 *  char *dest;
 *  struct CharAction (*charproc) ();

 * stream_get_sequence is a more primitive tokenizer than get_token.
 * it takes a procedure which for each character specifies whether the
 * character is to terminate the sequence, and whether or not the
 * character is to be included in the sequence.
 * (If the character terminates the sequence, but is not included, then
 * it will be seen again on the next call.)
 * For example, having seen a \"\, to read to the matching \"\, call
 * get_sequence with an action procedure that returns {TRUE, TRUE} for \"\
 * and  {FALSE, TRUE} for everything else. (If you want to detect the
 * case where a " is preceded by a \\, simply save the last character
 * and modify the procedure accordingly.

 * Note that gettoken can be defined in terms of get_sequence by
 * having Other characters return {FALSE, TRUE}, and also noticing whether
 * any have been seen yet, having Seprs return
 * {(seen_some_others ? TRUE : FALSE), FALSE}
 * and Break characters return {TRUE, (seen_some_others ? FALSE : TRUE)}

 * returns NULL for the empty sequence
 */

#ifndef EVERYTHING
#define EVERYTHING
struct CharAction xv_everything();
/* returns {FALSE, TRUE} for all characters */
#endif

/* GENERIC OUTPUT FUNCTIONS */

int stream_putc();
/* stream_putc(c, out)
 *  char        c;
 *  struct Stream   *out;
 * returns c if successful, otherwise EOF
 */

void stream_puts();
/* stream_puts(s, out)
 *  char        *s;
 *  struct Stream   *out;
 * analagous to puts:
 * writes s to out until a null is encountered (which is not written).
 * then writes a newline.
 */

void stream_fputs();
/* stream_fputs(s, out)
 *  char        *s;
 *  struct Stream   *out;
 * analagous to fputs, i.e. like stream_puts but does not include newline
 */

/* GENERIC FUNCTIONS THAT APPLY TO BOTH INPUT AND OUTPUT */

void stream_close();
/* void stream_close(stream)
 *  struct Stream   *stream;
 */

struct posrec stream_get_pos();
/* int stream_position(stream)
 *  STREAM  *stream;
 * returns number of lines and characters read from/ written to stream
 * lineno = -1, means stream doesn't know line number. This occurs
 * if stream has been reset via setpos, or implementor simply doesn't
 * bother to keep count
 * Note also that lineno may be inaccurate if someone calls puts
 * on a string which contains a newline in the middle somewhere.
 */

void stream_flush();
/* void stream_flush(out)
 *  struct Stream   *out;
 */

/* VARIOUS STREAM TYPES */

struct Stream *string_input_stream();
/* struct Stream *string_input_stream(s, in)
 *  char    *s;
 *  struct Stream   *in;
        if in =  NULL, creates new one, otherwise reuses this one
 */

struct Stream *string_output_stream();
/* struct Stream *string_output_stream(s, out)
 *  char    *s;
 *  struct Stream   *out;
        if out =  NULL, creates new one, otherwise reuses this one
 */

struct Stream *xv_file_input_stream();
/* struct Stream *xv_file_input_stream(s, fp)
 *  char    *s;
 *  FILE    *fp;
 *  if fp != NULL, it is used and s is ignored, otherwise
 * s is opened using fopen, with nmode "r"
 * e.g. xv_file_input_stream(NULL, STDIN) works.
 */

struct Stream *xv_file_output_stream();
/* struct Stream *xv_file_output_stream(s, fp, append)
 *  char    *s;
 *  FILE    *fp;
 *  Bool    append;
 *  if fp != NULL, it is used and s is ignored, otherwise
 * s is opened using fopen and mode "w" is append is FALSE, otherwise "a"
 * e.g. xv_file_output_stream(NULL, stdout) works.
 */

struct Stream *xv_filter_comments_stream();
/* struct Stream *xv_filter_comments_stream(in)
 *  struct Stream *in;
 *  creates a stream that obtains its input from in and discards all
 * characters that are inside of comments, where a comment is either
 * a line that begins with a #, or a sequence of characters bracketed by
 * slash* and *slash.
 */

#endif
