diff -upr hugs98-Mar2005-patched.orig/fptools/libraries/base/Foreign/C/String.hs hugs98-Mar2005-patched/fptools/libraries/base/Foreign/C/String.hs
--- hugs98-Mar2005-patched.orig/fptools/libraries/base/Foreign/C/String.hs	2005-01-28 22:36:26.000000000 +0900
+++ hugs98-Mar2005-patched/fptools/libraries/base/Foreign/C/String.hs	2005-03-24 14:38:48.000000000 +0900
@@ -30,8 +30,10 @@ module Foreign.C.String (   -- represent
 
   -- ** Using a locale-dependent encoding
 
+#ifndef __HUGS__
   -- | Currently these functions are identical to their @CAString@ counterparts;
   -- eventually they will use an encoding determined by the current locale.
+#endif
 
   -- conversion of C strings into Haskell strings
   --
@@ -88,6 +90,9 @@ module Foreign.C.String (   -- represent
 
   ) where
 
+#ifdef __HUGS__
+import Foreign.Marshal
+#endif
 import Foreign.Marshal.Array
 import Foreign.C.Types
 import Foreign.Ptr
@@ -128,12 +133,20 @@ type CStringLen = (Ptr CChar, Int)
 -- | Marshal a NUL terminated C string into a Haskell string.
 --
 peekCString    :: CString -> IO String
+#ifndef __HUGS__
 peekCString = peekCAString
+#else
+peekCString = peekCMBString
+#endif
 
 -- | Marshal a C string with explicit length into a Haskell string.
 --
 peekCStringLen           :: CStringLen -> IO String
+#ifndef __HUGS__
 peekCStringLen = peekCAStringLen
+#else
+peekCStringLen = peekCMBStringLen
+#endif
 
 -- | Marshal a Haskell string into a NUL terminated C string.
 --
@@ -144,7 +157,11 @@ peekCStringLen = peekCAStringLen
 --   'Foreign.Marshal.Alloc.finalizerFree'.
 --
 newCString :: String -> IO CString
+#ifndef __HUGS__
 newCString = newCAString
+#else
+newCString = newCMBString
+#endif
 
 -- | Marshal a Haskell string into a C string (ie, character array) with
 -- explicit length information.
@@ -154,7 +171,11 @@ newCString = newCAString
 --   'Foreign.Marshal.Alloc.finalizerFree'.
 --
 newCStringLen     :: String -> IO CStringLen
+#ifndef __HUGS__
 newCStringLen = newCAStringLen
+#else
+newCStringLen = newCMBStringLen
+#endif
 
 -- | Marshal a Haskell string into a NUL terminated C string using temporary
 -- storage.
@@ -166,7 +187,11 @@ newCStringLen = newCAStringLen
 --   storage must /not/ be used after this.
 --
 withCString :: String -> (CString -> IO a) -> IO a
+#ifndef __HUGS__
 withCString = withCAString
+#else
+withCString = withCMBString
+#endif
 
 -- | Marshal a Haskell string into a NUL terminated C string using temporary
 -- storage.
@@ -178,14 +203,23 @@ withCString = withCAString
 --   storage must /not/ be used after this.
 --
 withCStringLen         :: String -> (CStringLen -> IO a) -> IO a
+#ifndef __HUGS__
 withCStringLen = withCAStringLen
+#else
+withCStringLen = withCMBStringLen
+#endif
 
 -- | Determines whether a character can be accurately encoded in a 'CString'.
 -- Unrepresentable characters are converted to @\'?\'@.
 --
+#ifndef __HUGS__
 -- Currently only Latin-1 characters are representable.
 charIsRepresentable :: Char -> IO Bool
 charIsRepresentable c = return (ord c < 256)
+#else
+charIsRepresentable :: Char -> IO Bool
+charIsRepresentable = return . primIsRepresentable
+#endif
 
 -- single byte characters
 -- ----------------------
@@ -359,6 +393,121 @@ charsToCChars :: [Char] -> [CChar]
 charsToCChars xs  = map castCharToCChar xs
 #endif
 
+#ifdef __HUGS__
+-----------------------------------------------------------------------------
+-- Multi-byte character strings
+
+-- | Marshal a NUL terminated C string into a Haskell string.
+--
+peekCMBString    :: CString -> IO String
+peekCMBString cp =
+  alloca (\p -> do poke p cp; loop p)
+  where loop p = do
+             c <- primExtractChar p
+             if c == '\0'
+              then return []
+              else do
+                cs <- loop p
+                return (c : cs)
+
+-- | Marshal a C string with explicit length into a Haskell string.
+--
+peekCMBStringLen           :: CStringLen -> IO String
+peekCMBStringLen (cp, len) =
+  alloca $ \p ->
+    allocaArray (len + 1) $ \a -> do
+      copyArray a cp len
+      let end = a `plusPtr` len
+      poke end nUL
+      poke p a
+      loop end p
+  where
+    loop end p = do
+         cp <- peek p
+         if cp < end
+           then do
+             c  <- primExtractChar p
+             cs <- loop end p
+             return (c : cs)
+           else return []
+
+-- | Marshal a Haskell string into a NUL terminated C string.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * new storage is allocated for the C string and must be
+--   explicitly freed using 'Foreign.Marshal.Alloc.free' or
+--   'Foreign.Marshal.Alloc.finalizerFree'.
+--
+newCMBString :: String -> IO CString
+newCMBString str = alloca $ \p -> do
+  a <- mallocArray ((length str + 1) * primMaxCharEncoding)
+  poke p a
+  mapM_ (\c -> primAddChar c p) str
+  primAddChar '\0' p
+  return a
+
+-- | Marshal a Haskell string into a C string (ie, character array) with
+-- explicit length information.
+--
+-- * new storage is allocated for the C string and must be
+--   explicitly freed using 'Foreign.Marshal.Alloc.free' or
+--   'Foreign.Marshal.Alloc.finalizerFree'.
+--
+newCMBStringLen     :: String -> IO CStringLen
+newCMBStringLen str = do
+  a <- mallocArray (length str * primMaxCharEncoding)
+  len <- addChars a str
+  return (a,len)
+
+-- | Marshal a Haskell string into a NUL terminated C string using temporary
+-- storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * the memory is freed when the subcomputation terminates (either
+--   normally or via an exception), so the pointer to the temporary
+--   storage must /not/ be used after this.
+--
+withCMBString :: String -> (CString -> IO a) -> IO a
+withCMBString str act =  do
+  allocaArray ((length str + 1) * primMaxCharEncoding) $ \a ->
+    alloca $ \p -> do
+      poke p a
+      mapM_ (\c -> primAddChar c p) str
+      primAddChar '\0' p
+      act a
+
+-- | Marshal a Haskell string into a NUL terminated C string using temporary
+-- storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * the memory is freed when the subcomputation terminates (either
+--   normally or via an exception), so the pointer to the temporary
+--   storage must /not/ be used after this.
+--
+withCMBStringLen         :: String -> (CStringLen -> IO a) -> IO a
+withCMBStringLen str act = do
+  allocaArray (length str * primMaxCharEncoding) $ \ptr -> do
+    len <- addChars ptr str
+    act (ptr,len)
+
+primitive primIsRepresentable :: Char -> Bool
+primitive primMaxCharEncoding :: Int
+primitive primAddChar         :: Char -> Ptr CString -> IO ()
+primitive primExtractChar     :: Ptr CString -> IO Char
+
+addChars :: Ptr CChar -> String -> IO Int
+addChars buffer str =
+    alloca (\p -> 
+            do poke p buffer
+               mapM_ (\c -> primAddChar c p) str
+               end <- peek p
+               return (end `minusPtr` buffer))
+
+#endif /* __HUGS__ */
+
 -----------------------------------------------------------------------------
 -- Wide strings
 
diff -upr hugs98-Mar2005-patched.orig/src/builtin.c hugs98-Mar2005-patched/src/builtin.c
--- hugs98-Mar2005-patched.orig/src/builtin.c	2005-01-14 21:04:59.000000000 +0900
+++ hugs98-Mar2005-patched/src/builtin.c	2005-03-23 23:50:21.000000000 +0900
@@ -331,6 +331,10 @@ PROTO_PRIM(primToLower);
 PROTO_PRIM(primToTitle);
 PROTO_PRIM(primUniGenCat);
 #endif
+PROTO_PRIM(primIsRepresentable);
+PROTO_PRIM(primMaxCharEncoding);
+PROTO_PRIM(primAddChar);
+PROTO_PRIM(primExtractChar);
 
 #if TREX
 PROTO_PRIM(primRecExt);
@@ -550,6 +554,10 @@ static struct primitive builtinPrimTable
   {"toTitle",		1, primToTitle},
   {"primUniGenCat",	1, primUniGenCat},
 #endif
+  {"primMaxCharEncoding",	0,		primMaxCharEncoding},
+  {"primIsRepresentable",	1,		primIsRepresentable},
+  {"primAddChar",		2+IOArity,	primAddChar},
+  {"primExtractChar",		1+IOArity,	primExtractChar},
 
 #if TREX
   {"recExt",            3, primRecExt},
@@ -1459,6 +1467,26 @@ Char2Char(primToTitle,toTitle(x))
 Char2Int(primUniGenCat,uni_gencat(x))
 #endif
 
+CAFInt(primMaxCharEncoding,MAX_CHAR_ENCODING)
+Char2Bool(primIsRepresentable,charIsRepresentable(x))
+
+primFun(primAddChar) {
+    Char c;
+    char** p;
+    CharArg(c,2+IOArity);
+    PtrArg(p,1+IOArity);
+    AddChar(c,*p);
+    IOReturn(nameUnit);
+}
+
+primFun(primExtractChar) {
+    Char c;
+    char** p;
+    PtrArg(p,1+IOArity);
+    c = ExtractChar(*p);
+    IOReturn(mkChar(c));
+}
+
 /* --------------------------------------------------------------------------
  * Extensible records: (Gaster and Jones, 1996)
  * ------------------------------------------------------------------------*/
