<commit_before>%
% (c) The AQUA Project, Glasgow University, 1994-1996
%

\section[PrelHandle]{Module @PrelHandle@}

This module defines Haskell {\em handles} and the basic operations
which are supported for them.

\begin{code}
{-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
#include "cbits/error.h"

#ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
module PrelHandle where

import PrelBase
import PrelArr		( newVar, readVar, writeVar, ByteArray )
import PrelRead		( Read )
import PrelList 	( span )
import PrelIOBase
import PrelException 	( Exception(..), throw, catch, fail, catchException )
import PrelMaybe	( Maybe(..) )
import PrelAddr		( Addr, nullAddr )
import PrelBounded      ()   -- get at Bounded Int instance.
import PrelNum		( toInteger )
import PrelWeak		( addForeignFinaliser )
#if __CONCURRENT_HASKELL__
import PrelConc
#endif
import Ix

#ifndef __PARALLEL_HASKELL__
import PrelForeign  ( makeForeignObj, writeForeignObj )
#endif

#endif /* ndef(__HUGS__) */

#ifdef __HUGS__
#define cat2(x,y)  x/**/y
#define CCALL(fun) cat2(prim_,fun)
#define __CONCURRENT_HASKELL__
#define stToIO id
#define sizeof_int64 8
#else
#define CCALL(fun) _ccall_ fun
#define const_BUFSIZ ``BUFSIZ''
#define primPackString
#ifndef __PARALLEL_HASKELL__
#define FILE_OBJECT	    ForeignObj
#else
#define FILE_OBJECT	    Addr
#endif
#endif

\end{code}

%*********************************************************
%*							*
\subsection{Types @Handle@, @Handle__@}
%*							*
%*********************************************************

The @Handle@ and @Handle__@ types are defined in @IOBase@.

\begin{code}
{-# INLINE newHandle   #-}
{-# INLINE withHandle #-}
{-# INLINE writeHandle #-}
newHandle     :: Handle__ -> IO Handle
withHandle    :: Handle   -> (Handle__ -> IO a) -> IO a
writeHandle   :: Handle -> Handle__ -> IO ()

#if defined(__CONCURRENT_HASKELL__)

-- Use MVars for concurrent Haskell
newHandle hc  = newMVar	hc 	>>= \ h ->
	        return (Handle h)

  -- withHandle grabs the handle lock, performs
  -- some operation over it, making sure that we
  -- unlock & reset the handle state should an
  -- exception occur while performing said op.
withHandle (Handle h) act = do
   h_ <- takeMVar h
   v  <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
   return v
   
writeHandle (Handle h) hc = putMVar h hc
#else 

-- Use ordinary MutableVars for non-concurrent Haskell
newHandle hc  = stToIO (newVar	hc 	>>= \ h ->
		        return (Handle h))

   -- of questionable value to install this exception
   -- handler, but let's do it in the non-concurrent
   -- case too, for now.
withHandle (Handle h) act = do
   h_ <- stToIO (readVar h)
   v  <- catchException (act h_) (\ ex -> stToIO (writeVar h h_) >> throw ex)
   return v

writeHandle (Handle h) hc = stToIO (writeVar h hc)
#endif

\end{code}

nullFile__ is only used for closed handles, plugging it in as a null
file object reference.

\begin{code}
nullFile__ :: FILE_OBJECT
nullFile__ = 
#ifndef __PARALLEL_HASKELL__
    unsafePerformIO (makeForeignObj nullAddr)
#else
    nullAddr
#endif


mkClosedHandle__ :: Handle__
mkClosedHandle__ = 
  Handle__ 
	   nullFile__
	   ClosedHandle 
	   NoBuffering
	   "closed file"

mkErrorHandle__ :: IOError -> Handle__
mkErrorHandle__ ioe =
  Handle__
           nullFile__ 
	   (ErrorHandle ioe)
	   NoBuffering
	   "error handle"
\end{code}

%*********************************************************
%*							*
\subsection{Handle Finalisers}
%*							*
%*********************************************************

\begin{code}
#ifndef __HUGS__
freeStdFileObject :: ForeignObj -> IO ()
freeStdFileObject fo = CCALL(freeStdFileObject) fo

freeFileObject :: ForeignObj -> IO ()
freeFileObject fo = CCALL(freeFileObject) fo
#else
foreign import stdcall "./libHS_cbits.dll" "freeStdFileObject" freeStdFileObject :: ForeignObj -> IO ()
foreign import stdcall "./libHS_cbits.dll" "freeFileObject" freeFileObject :: ForeignObj -> IO ()
#endif
\end{code}

%*********************************************************
%*							*
\subsection[StdHandles]{Standard handles}
%*							*
%*********************************************************

Three handles are allocated during program initialisation.  The first
two manage input or output from the Haskell program's standard input
or output channel respectively.  The third manages output to the
standard error channel. These handles are initially open.

\begin{code}
stdin, stdout, stderr :: Handle
<commit_msg>[project @ 1999-01-12 14:03:27 by sewardj] Made FILE_OBJECT be defined for -D__HUGS__. Changed .dll file refs to .so for -D__HUGS__.<commit_after>
% (c) The AQUA Project, Glasgow University, 1994-1996
%

\section[PrelHandle]{Module @PrelHandle@}

This module defines Haskell {\em handles} and the basic operations
which are supported for them.

\begin{code}
{-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
#include "cbits/error.h"

#ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
module PrelHandle where

import PrelBase
import PrelArr		( newVar, readVar, writeVar, ByteArray )
import PrelRead		( Read )
import PrelList 	( span )
import PrelIOBase
import PrelException 	( Exception(..), throw, catch, fail, catchException )
import PrelMaybe	( Maybe(..) )
import PrelAddr		( Addr, nullAddr )
import PrelBounded      ()   -- get at Bounded Int instance.
import PrelNum		( toInteger )
import PrelWeak		( addForeignFinaliser )
#if __CONCURRENT_HASKELL__
import PrelConc
#endif
import Ix

#ifndef __PARALLEL_HASKELL__
import PrelForeign  ( makeForeignObj, writeForeignObj )
#endif

#endif /* ndef(__HUGS__) */

#ifdef __HUGS__
#define cat2(x,y)  x/**/y
#define CCALL(fun) cat2(prim_,fun)
#define __CONCURRENT_HASKELL__
#define stToIO id
#define sizeof_int64 8
#else
#define CCALL(fun) _ccall_ fun
#define const_BUFSIZ ``BUFSIZ''
#define primPackString
#endif

#ifndef __PARALLEL_HASKELL__
#define FILE_OBJECT	    ForeignObj
#else
#define FILE_OBJECT	    Addr
#endif

\end{code}

%*********************************************************
%*							*
\subsection{Types @Handle@, @Handle__@}
%*							*
%*********************************************************

The @Handle@ and @Handle__@ types are defined in @IOBase@.

\begin{code}
{-# INLINE newHandle   #-}
{-# INLINE withHandle #-}
{-# INLINE writeHandle #-}
newHandle     :: Handle__ -> IO Handle
withHandle    :: Handle   -> (Handle__ -> IO a) -> IO a
writeHandle   :: Handle -> Handle__ -> IO ()

#if defined(__CONCURRENT_HASKELL__)

-- Use MVars for concurrent Haskell
newHandle hc  = newMVar	hc 	>>= \ h ->
	        return (Handle h)

  -- withHandle grabs the handle lock, performs
  -- some operation over it, making sure that we
  -- unlock & reset the handle state should an
  -- exception occur while performing said op.
withHandle (Handle h) act = do
   h_ <- takeMVar h
   v  <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
   return v
   
writeHandle (Handle h) hc = putMVar h hc
#else 

-- Use ordinary MutableVars for non-concurrent Haskell
newHandle hc  = stToIO (newVar	hc 	>>= \ h ->
		        return (Handle h))

   -- of questionable value to install this exception
   -- handler, but let's do it in the non-concurrent
   -- case too, for now.
withHandle (Handle h) act = do
   h_ <- stToIO (readVar h)
   v  <- catchException (act h_) (\ ex -> stToIO (writeVar h h_) >> throw ex)
   return v

writeHandle (Handle h) hc = stToIO (writeVar h hc)
#endif

\end{code}

nullFile__ is only used for closed handles, plugging it in as a null
file object reference.

\begin{code}
nullFile__ :: FILE_OBJECT
nullFile__ = 
#ifndef __PARALLEL_HASKELL__
    unsafePerformIO (makeForeignObj nullAddr)
#else
    nullAddr
#endif


mkClosedHandle__ :: Handle__
mkClosedHandle__ = 
  Handle__ 
	   nullFile__
	   ClosedHandle 
	   NoBuffering
	   "closed file"

mkErrorHandle__ :: IOError -> Handle__
mkErrorHandle__ ioe =
  Handle__
           nullFile__ 
	   (ErrorHandle ioe)
	   NoBuffering
	   "error handle"
\end{code}

%*********************************************************
%*							*
\subsection{Handle Finalisers}
%*							*
%*********************************************************

\begin{code}
#ifndef __HUGS__
freeStdFileObject :: ForeignObj -> IO ()
freeStdFileObject fo = CCALL(freeStdFileObject) fo

freeFileObject :: ForeignObj -> IO ()
freeFileObject fo = CCALL(freeFileObject) fo
#else
foreign import stdcall "libHS_cbits.so" "freeStdFileObject" freeStdFileObject :: ForeignObj -> IO ()
foreign import stdcall "libHS_cbits.so" "freeFileObject" freeFileObject :: ForeignObj -> IO ()
#endif
\end{code}

%*********************************************************
%*							*
\subsection[StdHandles]{Standard handles}
%*							*
%*********************************************************

Three handles are allocated during program initialisation.  The first
two manage input or output from the Haskell program's standard input
or output channel respectively.  The third manages output to the
standard error channel. These handles are initially open.

\begin{code}
stdin, stdout, stderr :: Handle

{'fraction_non_alphanumeric': 0.16803233912378454, 'fraction_numerical': 0.004370151862777232, 'mean_word_length': 4.065855008301051, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2820334', 'n_tokens_mistral': 3064, 'n_tokens_neox': 2854, 'n_words': 912}