--- /dev/null
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[CharSeq]{Characters sequences: the @CSeq@ type}
+
+\begin{code}
+#if defined(COMPILING_GHC)
+# include "HsVersions.h"
+#else
+# define FAST_STRING String
+# define FAST_INT Int
+# define ILIT(x) (x)
+# define IBOX(x) (x)
+# define _GE_ >=
+# define _ADD_ +
+# define _SUB_ -
+# define FAST_BOOL Bool
+# define _TRUE_ True
+# define _FALSE_ False
+#endif
+
+module CharSeq (
+ CSeq,
+ cNil, cAppend, cIndent, cNL, cStr, cPStr, cCh, cInt,
+#if ! defined(COMPILING_GHC)
+ cLength,
+ cShows,
+#endif
+ cShow
+
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 22
+ , cAppendFile
+ ) where
+
+#if __GLASGOW_HASKELL__ < 26
+import PreludePrimIO
+#endif
+import PreludeGlaST
+
+#else
+ ) where
+#endif
+\end{code}
+
+%************************************************
+%* *
+ \subsection{The interface}
+%* *
+%************************************************
+
+\begin{code}
+cShow :: CSeq -> [Char]
+
+#if ! defined(COMPILING_GHC)
+-- not used in GHC
+cShows :: CSeq -> ShowS
+cLength :: CSeq -> Int
+#endif
+
+cNil :: CSeq
+cAppend :: CSeq -> CSeq -> CSeq
+cIndent :: Int -> CSeq -> CSeq
+cNL :: CSeq
+cStr :: [Char] -> CSeq
+cPStr :: FAST_STRING -> CSeq
+cCh :: Char -> CSeq
+cInt :: Int -> CSeq
+
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 22
+
+# if __GLASGOW_HASKELL__ < 23
+# define _FILE _Addr
+# endif
+
+cAppendFile :: _FILE -> CSeq -> PrimIO ()
+#endif
+\end{code}
+
+%************************************************
+%* *
+ \subsection{The representation}
+%* *
+%************************************************
+
+\begin{code}
+data CSeq
+ = CNil
+ | CAppend CSeq CSeq
+ | CIndent Int CSeq
+ | CNewline -- Move to start of next line, unless we're
+ -- already at the start of a line.
+ | CStr [Char]
+ | CCh Char
+ | CInt Int -- equiv to "CStr (show the_int)"
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 23
+ | CPStr _PackedString
+#endif
+\end{code}
+
+The construction functions do pattern matching, to ensure that
+redundant CNils are eliminated. This is bound to have some effect on
+evaluation order, but quite what I don't know.
+
+\begin{code}
+cNil = CNil
+\end{code}
+
+The following special cases were eating our lunch! They make the whole
+thing too strict. A classic strictness bug!
+\begin{code}
+-- cAppend CNil cs2 = cs2
+-- cAppend cs1 CNil = cs1
+
+cAppend cs1 cs2 = CAppend cs1 cs2
+
+cIndent n cs = CIndent n cs
+
+cNL = CNewline
+cStr = CStr
+cCh = CCh
+cInt = CInt
+
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 23
+cPStr = CPStr
+#else
+cPStr = CStr
+#endif
+
+cShow seq = flatten ILIT(0) _TRUE_ seq []
+
+#if ! defined(COMPILING_GHC)
+cShows seq rest = cShow seq ++ rest
+cLength seq = length (cShow seq) -- *not* the best way to do this!
+#endif
+
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 22
+cAppendFile file_star seq
+ = flattenIO file_star seq
+#endif
+\end{code}
+
+This code is {\em hammered}. We are not above doing sleazy
+non-standard things. (WDP 94/10)
+
+\begin{code}
+data WorkItem = WI FAST_INT CSeq -- indentation, and sequence
+
+flatten :: FAST_INT -- Indentation
+ -> FAST_BOOL -- True => just had a newline
+ -> CSeq -- Current seq to flatten
+ -> [WorkItem] -- Work list with indentation
+ -> String
+
+flatten n nlp CNil seqs = flattenS nlp seqs
+
+flatten n nlp (CAppend seq1 seq2) seqs = flatten n nlp seq1 ((WI n seq2) : seqs)
+flatten n nlp (CIndent IBOX(n2) seq) seqs = flatten (n2 _ADD_ n) nlp seq seqs
+
+flatten n _FALSE_ CNewline seqs = '\n' : flattenS _TRUE_ seqs
+flatten n _TRUE_ CNewline seqs = flattenS _TRUE_ seqs -- Already at start of line
+
+flatten n _FALSE_ (CStr s) seqs = s ++ flattenS _FALSE_ seqs
+flatten n _FALSE_ (CCh c) seqs = c : flattenS _FALSE_ seqs
+flatten n _FALSE_ (CInt i) seqs = show i ++ flattenS _FALSE_ seqs
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 23
+flatten n _FALSE_ (CPStr s) seqs = _unpackPS s ++ flattenS _FALSE_ seqs
+#endif
+
+flatten n _TRUE_ (CStr s) seqs = mkIndent n (s ++ flattenS _FALSE_ seqs)
+flatten n _TRUE_ (CCh c) seqs = mkIndent n (c : flattenS _FALSE_ seqs)
+flatten n _TRUE_ (CInt i) seqs = mkIndent n (show i ++ flattenS _FALSE_ seqs)
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 23
+flatten n _TRUE_ (CPStr s) seqs = mkIndent n (_unpackPS s ++ flattenS _FALSE_ seqs)
+#endif
+\end{code}
+
+\begin{code}
+flattenS :: FAST_BOOL -> [WorkItem] -> String
+flattenS nlp [] = ""
+flattenS nlp ((WI col seq):seqs) = flatten col nlp seq seqs
+\end{code}
+
+\begin{code}
+mkIndent :: FAST_INT -> String -> String
+mkIndent ILIT(0) s = s
+mkIndent n s
+ = if (n _GE_ ILIT(8))
+ then '\t' : mkIndent (n _SUB_ ILIT(8)) s
+ else ' ' : mkIndent (n _SUB_ ILIT(1)) s
+ -- Hmm.. a little Unix-y.
+\end{code}
+
+Now the I/O version.
+This code is massively {\em hammered}.
+It {\em ignores} indentation.
+
+\begin{code}
+#if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 22
+
+flattenIO :: _FILE -- file we are writing to
+ -> CSeq -- Seq to print
+ -> PrimIO ()
+
+flattenIO file sq
+# if __GLASGOW_HASKELL__ >= 23
+ | file == ``NULL'' = error "panic:flattenIO" -- really just to force eval :-)
+ | otherwise
+# endif
+ = flat sq
+ where
+ flat CNil = BSCC("flatCNil") returnPrimIO () ESCC
+
+ flat (CIndent n2 seq) = BSCC("flatCIndent") flat seq ESCC
+
+ flat (CAppend seq1 seq2)
+ = BSCC("flatCAppend")
+ flat seq1 `seqPrimIO` flat seq2
+ ESCC
+
+ flat CNewline = BSCC("flatCNL") _ccall_ stg_putc '\n' file ESCC
+
+ flat (CCh c) = BSCC("flatCCh") _ccall_ stg_putc c file ESCC
+
+ flat (CInt i) = BSCC("flatCInt") _ccall_ fprintf file percent_d i ESCC
+
+ flat (CStr s) = BSCC("flatCStr") put_str s ESCC
+
+# if defined(COMPILING_GHC) && __GLASGOW_HASKELL__ >= 23
+ flat (CPStr s) = BSCC("flatCPStr") put_pstr s ESCC
+# endif
+
+ -----
+ put_str, put_str2 :: String -> PrimIO ()
+
+ put_str str
+ = --put_str2 ``stderr'' (str ++ "\n") `seqPrimIO`
+ put_str2 str
+
+ put_str2 [] = BSCC("putNil") returnPrimIO () ESCC
+
+ put_str2 (c1@(C# _) : c2@(C# _) : c3@(C# _) : c4@(C# _) : cs)
+ = BSCC("put4")
+ _ccall_ stg_putc c1 file `seqPrimIO`
+ _ccall_ stg_putc c2 file `seqPrimIO`
+ _ccall_ stg_putc c3 file `seqPrimIO`
+ _ccall_ stg_putc c4 file `seqPrimIO`
+ put_str2 cs -- efficiency hack? who knows... (WDP 94/10)
+ ESCC
+
+ put_str2 (c1@(C# _) : c2@(C# _) : c3@(C# _) : cs)
+ = BSCC("put3")
+ _ccall_ stg_putc c1 file `seqPrimIO`
+ _ccall_ stg_putc c2 file `seqPrimIO`
+ _ccall_ stg_putc c3 file `seqPrimIO`
+ put_str2 cs -- efficiency hack? who knows... (WDP 94/10)
+ ESCC
+
+ put_str2 (c1@(C# _) : c2@(C# _) : cs)
+ = BSCC("put2")
+ _ccall_ stg_putc c1 file `seqPrimIO`
+ _ccall_ stg_putc c2 file `seqPrimIO`
+ put_str2 cs -- efficiency hack? who knows... (WDP 94/10)
+ ESCC
+
+ put_str2 (c1@(C# _) : cs)
+ = BSCC("put1")
+ _ccall_ stg_putc c1 file `seqPrimIO`
+ put_str2 cs -- efficiency hack? who knows... (WDP 94/10)
+ ESCC
+
+# if __GLASGOW_HASKELL__ >= 23
+ put_pstr ps = _putPS file ps
+# endif
+
+# if __GLASGOW_HASKELL__ >= 23
+percent_d = _psToByteArray SLIT("%d")
+# else
+percent_d = "%d"
+# endif
+
+#endif {- __GLASGOW_HASKELL__ >= 22 -}
+\end{code}