// Additional functions.
//
// ----------------------------------------------------------------------
// This file is part of ILOG Talk.
// Inquiries to ILOG S.A.
//              9 rue de Verdun, BP 85,
//              94253 Gentilly Cedex, France.
//
// Copyright (c) 1995-1996 by ILOG
// ----------------------------------------------------------------------
//
// Note: don't even think about providing cin, cout and cerr functions
// in Talk using externals of the form:
//
//	void *ilt_cout() { return cout; }
//
// since cin, cout and cerr are not mere istreams or ostreams, as one
// could expect.

#include <iltsystem.h>
#include <iostream.h>

#if defined(ILT_OS_WIN32)
#	include <windows.h>
#	include <fstream.h>
#endif

#if defined(ILT_CPP_GCC)
	/* When using g++, we also use libg++. */
#	include <streambuf.h>
#endif

#if defined(ILT_DO_IT_RIGHT)
#	include <fstream.h>
#endif

extern "C"
{
#if defined(ILT_OS_WIN32)

    extern HANDLE ilt_win32_fd_handle(int);
    extern int _open_osfhandle(long, int);

    static int ilt_win32_fd_cfd(int fd)
    {
        HANDLE h = ilt_win32_fd_handle(fd);
	return _open_osfhandle((long)h, 0);
    }

    void *ilt_istream(int fd)
    {
        int cfd = ilt_win32_fd_cfd(fd);
    	filebuf *fbuf = new filebuf(cfd);
	istream *is = new istream(fbuf);
	return is;
    }

    void *ilt_ostream(int fd)
    {
        int cfd = ilt_win32_fd_cfd(fd);
    	filebuf *fbuf = new filebuf(cfd);
	ostream *os = new ostream(fbuf);
	return os;
    }

#else /* defined(ILT_OS_WIN32) */

#if defined(ILT_CPP_GCC)

#if defined(ILT_OS_UNIX_LINUX)

    void *ilt_istream(int fd)
    {
	return new istream (new filebuf (fd));
    }

    void *ilt_ostream(int fd)
    {
	return new ostream (new filebuf (fd));
    }

#else

    /* libg++ 2.7.1 is apparently missing some functions. */

    void *ilt_istream(int fd)
    {
	return (istream *) (new iostream (new filebuf (fd)));
    }

    void *ilt_ostream(int fd)
    {
	return (ostream *) (new iostream (new filebuf (fd)));
    }

#endif

#else /* defined(ILT_CPP_GCC) */

#if defined(ILT_DO_IT_RIGHT)

    /* Maybe this is more portable. */

    void *ilt_istream(int fd)
    {
	return new ifstream(fd);
    }

    void *ilt_ostream(int fd)
    {
	return new ofstream(fd);
    }

#else /* defined(ILT_DO_IT_RIGHT) */

    /* Sloppy Unix code. */

    void *ilt_istream(int fd)
    {
	return new istream(fd);
    }

    void *ilt_ostream(int fd)
    {
	return new ostream(fd);
    }

#endif /* defined(ILT_DO_IT_RIGHT) */

#endif /* defined(ILT_CPP_GCC) */

#endif /* defined(ILT_OS_WIN32) */
}
