diff --git a/AUTHORS b/AUTHORS
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,6 +7,7 @@
 Acknowledgements:
 Neil Mitchell (bug reports)
 Jeremy Gibbons (bug reports)
+Justin Bailey (line numbering improvements)
 
 If you are not listed here, but feel
 that you should be, please let me know.
diff --git a/INSTALL b/INSTALL
--- a/INSTALL
+++ b/INSTALL
@@ -32,7 +32,7 @@
 Unpack the archive. Assume that it has been unpacked into directory
 "/somewhere". Then say
 
-cd /somewhere/lhs2TeX-1.17
+cd /somewhere/lhs2TeX-1.18
 ./configure
 make
 make install
@@ -48,18 +48,18 @@
 lhs2TeX binary. The default search path is as follows:
 
 .
-{HOME}/lhs2tex-1.17//
+{HOME}/lhs2tex-1.18//
 {HOME}/lhs2tex//
 {HOME}/lhs2TeX//
-{HOME}/.lhs2tex-1.17//
+{HOME}/.lhs2tex-1.18//
 {HOME}/.lhs2tex//
 {HOME}/.lhs2TeX//
 {LHS2TEX}//
-/usr/local/share/lhs2tex-1.17//
-/usr/local/share/lhs2tex-1.17//
-/usr/local/lib/lhs2tex-1.17//
-/usr/share/lhs2tex-1.17//
-/usr/lib/lhs2tex-1.17//
+/usr/local/share/lhs2tex-1.18//
+/usr/local/share/lhs2tex-1.18//
+/usr/local/lib/lhs2tex-1.18//
+/usr/share/lhs2tex-1.18//
+/usr/lib/lhs2tex-1.18//
 /usr/local/share/lhs2tex//
 /usr/local/lib/lhs2tex//
 /usr/share/lhs2tex//
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,8 @@
                    src/MathCommon.lhs src/NewCode.lhs \
 		   src/Directives.lhs src/HsLexer.lhs src/FileNameUtils.lhs \
 		   src/Parser.lhs src/FiniteMap.lhs src/Auxiliaries.lhs \
-		   src/StateT.lhs src/Document.lhs src/Verbatim.lhs src/Value.lhs
+		   src/StateT.lhs src/Document.lhs src/Verbatim.lhs src/Value.lhs \
+		   src/License.lhs src/State.lhs
 sources         := $(psources) src/Version.lhs
 snipssrc        := sorts.snip id.snip cata.snip spec.snip
 snips	        := sorts.tt sorts.math id.math cata.math spec.math
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -19,12 +19,12 @@
 import Data.List (isSuffixOf,isPrefixOf)
 import Data.Maybe (listToMaybe,isJust)
 import Data.Version
+import Control.Exception (try)
 import Control.Monad (when,unless)
 import Text.Regex (matchRegex,matchRegexAll,mkRegex,mkRegexWithOpts,subRegex)
 import Text.ParserCombinators.ReadP (readP_to_S)
 import System.Exit
 import System.IO (hGetContents,hClose,hPutStr,stderr)
-import System.IO.Error (try)
 import System.Process (runInteractiveProcess,waitForProcess)
 import System.Directory
 import System.Info (os)
@@ -33,9 +33,9 @@
 minPolytableVersion = [0,8,2]
 shortversion = show (numversion `div` 100) ++ "." ++ show (numversion `mod` 100)
 version = shortversion ++ if ispre then "pre" ++ show pre else ""
-numversion = 117
+numversion = 118
 ispre = False
-pre = 2
+pre = 1
 
 main = defaultMainWithHooks lhs2texHooks
 
@@ -77,7 +77,7 @@
                          else do  (_,b,_) <- (runKpseWhichVar "TEXMFMAIN")
                                   return . stripQuotes . stripNewlines $ b
         ex      <- return (not . all isSpace $ b) -- or check if directory exists?
-        i       <- if ex then 
+        i       <- if ex then
                    do  (_,p,_) <- runKpseWhich "polytable.sty"
                        p       <- return . stripNewlines $ p
                        ex      <- doesFileExist p
@@ -124,6 +124,7 @@
                                                   replace "@VERSION@" version .
                                                   replace "@SHORTVERSION@" shortversion .
                                                   replace "@NUMVERSION@" (show numversion) .
+                                                  replace "@SEP@" sep .
                                                   replace "@PRE@" (show pre) >>= writeFile f)
               generatedFiles
   where runKpseWhich v = runCommandProgramConf silent "kpsewhich" (withPrograms lbi) [v]
@@ -236,8 +237,8 @@
 
 lhs2texCleanHook pd lbi v pshs =
     do  cleanHook simpleUserHooks pd lbi v pshs
-        try $ removeFile lhs2texBuildInfoFile
-        mapM_ (try . removeFile) generatedFiles
+        tryIO $ removeFile lhs2texBuildInfoFile
+        mapM_ (tryIO . removeFile) generatedFiles
 
 matchRegexRepeatedly re str =
     case matchRegexAll re str of
@@ -251,7 +252,7 @@
     escapeRegex []        = []
     escapeRegex ('\\':xs) = '\\':'\\': escapeRegex xs
     escapeRegex (x:xs)    = x : escapeRegex xs
-    
+
 escapeChars :: String -> String
 escapeChars t = foldr showLitChar [] t
 
@@ -273,9 +274,9 @@
                      ++ [ "-o" ++ outf ]
                      ++ (if v == deafening then ["-v"] else [])
                      ++ params
-	(ex,_,err) <- runCommand v lhs2texBin args
-	hPutStr stderr (unlines . lines $ err)
-	maybeExit (return ex)
+        (ex,_,err) <- runCommand v lhs2texBin args
+        hPutStr stderr (unlines . lines $ err)
+        maybeExit (return ex)
 
 runCommandProgramConf  ::  Verbosity              -- ^ verbosity
                        ->  String                 -- ^ program name
@@ -287,7 +288,7 @@
         runCommand v prog (args ++ extraArgs)
 
 getProgram :: String -> ProgramConfiguration -> IO (String, [String])
-getProgram progName programConf = 
+getProgram progName programConf =
              do  let mProg = lookupProgram (simpleProgram progName) programConf
                  case mProg of
                    Just (ConfiguredProgram { programLocation = UserSpecified p,
@@ -302,7 +303,7 @@
                  ->  [String]              -- ^ args
                  ->  [(String,String)]     -- ^ the environment
                  ->  IO (ExitCode,String,String)
-runCommandInEnv v cmd args env = 
+runCommandInEnv v cmd args env =
                  do  when (v >= verbose) $ putStrLn (cmd ++ concatMap (' ':) args)
                      let env' = if null env then Nothing else Just env
                      (cin,cout,cerr,pid) <- runInteractiveProcess cmd args Nothing env'
@@ -341,6 +342,9 @@
   writeFile lhs2texBuildInfoFile (show lbi)
 
 
+tryIO :: IO a -> IO (Either IOError a)
+tryIO = try
+
 -- HACKS because the Cabal API isn't sufficient:
 
 -- Distribution.Compat.FilePath is supposed to be hidden in future
@@ -352,7 +356,7 @@
 joinFileName dir fname
   | isPathSeparator (last dir) = dir++fname
   | otherwise                  = dir++pathSeparator:fname
-  where 
+  where
  isPathSeparator :: Char -> Bool
  isPathSeparator | isWindows = ( `elem` "/\\" )
                  | otherwise = ( == '/' )
@@ -360,4 +364,4 @@
                  | otherwise = '/'
 
 -- It would be nice if there'd be a predefined way to detect this
-isWindows = "mingw" `isPrefixOf` os || "win" `isPrefixOf` os 
+isWindows = "mingw" `isPrefixOf` os || "win" `isPrefixOf` os
diff --git a/Testsuite/Makefile b/Testsuite/Makefile
--- a/Testsuite/Makefile
+++ b/Testsuite/Makefile
@@ -7,7 +7,8 @@
                    src/MathCommon.lhs src/NewCode.lhs \
 		   src/Directives.lhs src/HsLexer.lhs src/FileNameUtils.lhs \
 		   src/Parser.lhs src/FiniteMap.lhs src/Auxiliaries.lhs \
-		   src/StateT.lhs src/Document.lhs src/Verbatim.lhs src/Value.lhs
+		   src/StateT.lhs src/Document.lhs src/Verbatim.lhs src/Value.lhs \
+		   src/License.lhs src/State.lhs
 sources         := $(psources) src/Version.lhs
 snipssrc        := sorts.snip id.snip cata.snip spec.snip
 snips	        := sorts.tt sorts.math id.math cata.math spec.math
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -1,11 +1,9 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for lhs2tex 1.17.
+# Generated by GNU Autoconf 2.69 for lhs2tex 1.18.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -134,6 +132,31 @@
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -167,7 +190,8 @@
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -211,21 +235,25 @@
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-	# neutralization value for shells without unset; and this also
-	# works around shells that cannot unset nonexistent variables.
-	# Preserve -v and -x to the replacement shell.
-	BASH_ENV=/dev/null
-	ENV=/dev/null
-	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-	export CONFIG_SHELL
-	case $- in # ((((
-	  *v*x* | *x*v* ) as_opts=-vx ;;
-	  *v* ) as_opts=-v ;;
-	  *x* ) as_opts=-x ;;
-	  * ) as_opts= ;;
-	esac
-	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -327,6 +355,14 @@
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -448,6 +484,10 @@
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -482,16 +522,16 @@
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -503,28 +543,8 @@
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -556,13 +576,14 @@
 # Identity of this package.
 PACKAGE_NAME='lhs2tex'
 PACKAGE_TARNAME='lhs2tex'
-PACKAGE_VERSION='1.17'
-PACKAGE_STRING='lhs2tex 1.17'
+PACKAGE_VERSION='1.18'
+PACKAGE_STRING='lhs2tex 1.18'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
+SEP
 LHS2TEX
 stydir
 MKTEXLSR
@@ -1097,8 +1118,6 @@
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1184,7 +1203,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures lhs2tex 1.17 to adapt to many kinds of systems.
+\`configure' configures lhs2tex 1.18 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1245,7 +1264,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of lhs2tex 1.17:";;
+     short | recursive ) echo "Configuration of lhs2tex 1.18:";;
    esac
   cat <<\_ACEOF
 
@@ -1323,10 +1342,10 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-lhs2tex configure 1.17
-generated by GNU Autoconf 2.68
+lhs2tex configure 1.18
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1340,8 +1359,8 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by lhs2tex $as_me 1.17, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+It was created by lhs2tex $as_me 1.18, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -1689,10 +1708,10 @@
 
 
 
-VERSION="1.17"
-SHORTVERSION="1.17"
-NUMVERSION=117
-PRE=2
+VERSION="1.18"
+SHORTVERSION="1.18"
+NUMVERSION=118
+PRE=1
 
 
 
@@ -1717,7 +1736,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GHC="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -1758,7 +1777,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_HUGS="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -1848,7 +1867,7 @@
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
 	  if test $ac_prog = install &&
 	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
 	    # AIX install.  It has an incompatible calling convention.
@@ -1937,7 +1956,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -1977,7 +1996,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2017,7 +2036,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2057,7 +2076,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2097,7 +2116,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_TOUCH="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2137,7 +2156,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_DIFF="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2177,7 +2196,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2217,7 +2236,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2257,7 +2276,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_SORT="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2297,7 +2316,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_UNIQ="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2337,7 +2356,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2377,7 +2396,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2417,7 +2436,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PDFLATEX="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2457,7 +2476,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_XDVI="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2497,7 +2516,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GV="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2537,7 +2556,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_DVIPS="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2589,7 +2608,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_KPSEWHICH="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2747,7 +2766,7 @@
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MKTEXLSR="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2780,6 +2799,10 @@
 LHS2TEX="../lhs2TeX"
 
 
+# search path separator
+SEP=":"
+
+
 ac_config_files="$ac_config_files config.mk src/Version.lhs lhs2TeX.1 doc/InteractiveHugs.lhs doc/InteractivePre.lhs"
 
 cat >confcache <<\_ACEOF
@@ -3225,16 +3248,16 @@
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -3294,29 +3317,17 @@
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
 
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 
@@ -3336,8 +3347,8 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by lhs2tex $as_me 1.17, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+This file was extended by lhs2tex $as_me 1.18, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -3389,11 +3400,11 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-lhs2tex config.status 1.17
-configured by $0, generated by GNU Autoconf 2.68,
+lhs2tex config.status 1.18
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -3471,7 +3482,7 @@
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
diff --git a/doc/Guide2.pdf b/doc/Guide2.pdf
Binary files a/doc/Guide2.pdf and b/doc/Guide2.pdf differ
diff --git a/doc/InteractivePre.lhs.in b/doc/InteractivePre.lhs.in
--- a/doc/InteractivePre.lhs.in
+++ b/doc/InteractivePre.lhs.in
@@ -14,7 +14,7 @@
 %format ^^     = "\; "
 %endif
 
-%options ghci -fth -pgmL "@LHS2TEX@" -optL-Pdoc: -optL--pre
+%options ghci -fth -pgmL "@LHS2TEX@" -optL-Pdoc@SEP@ -optL--pre
 
 This is a rather stupid way of computing |42| using
 Template Haskell:
diff --git a/doc/RawSearchPath.lhs b/doc/RawSearchPath.lhs
--- a/doc/RawSearchPath.lhs
+++ b/doc/RawSearchPath.lhs
@@ -1,17 +1,17 @@
 \begin{code}
 .
-{HOME}/lhs2tex-1.17//
+{HOME}/lhs2tex-1.18//
 {HOME}/lhs2tex//
 {HOME}/lhs2TeX//
-{HOME}/.lhs2tex-1.17//
+{HOME}/.lhs2tex-1.18//
 {HOME}/.lhs2tex//
 {HOME}/.lhs2TeX//
 {LHS2TEX}//
-/usr/local/share/lhs2tex-1.17//
-/usr/local/share/lhs2tex-1.17//
-/usr/local/lib/lhs2tex-1.17//
-/usr/share/lhs2tex-1.17//
-/usr/lib/lhs2tex-1.17//
+/usr/local/share/lhs2tex-1.18//
+/usr/local/share/lhs2tex-1.18//
+/usr/local/lib/lhs2tex-1.18//
+/usr/share/lhs2tex-1.18//
+/usr/lib/lhs2tex-1.18//
 /usr/local/share/lhs2tex//
 /usr/local/lib/lhs2tex//
 /usr/share/lhs2tex//
diff --git a/lhs2tex.cabal b/lhs2tex.cabal
--- a/lhs2tex.cabal
+++ b/lhs2tex.cabal
@@ -1,6 +1,6 @@
 cabal-version:  >=1.10
 name:           lhs2tex
-version:        1.17
+version:        1.18
 license:        GPL
 license-file:   LICENSE
 author:         Ralf Hinze <ralf.hinze@comlab.ox.ac.uk>, Andres Loeh <lhs2tex@andres-loeh.de>
@@ -16,11 +16,34 @@
   main-is:              Main.lhs
   hs-source-dirs:       src
   default-language:     Haskell98
+  other-extensions:     ScopedTypeVariables
+                        NPlusKPatterns
+                        GeneralizedNewtypeDeriving
+                        TypeSynonymInstances
   build-depends:        base >= 4.2 && < 5,
                         regex-compat,
                         mtl,
                         filepath,
                         directory,
-                        process,
-                        extensible-exceptions
-
+                        process
+  other-modules:        Auxiliaries
+                        Directives
+                        Document
+                        FileNameUtils
+                        FiniteMap
+                        HsLexer
+                        LaTeX
+                        License
+                        MathCommon
+                        Math
+                        MathPoly
+                        NewCode
+                        Parser
+                        State
+                        StateT
+                        TeXCommands
+                        TeXParser
+                        Typewriter
+                        Value
+                        Verbatim
+                        Version
diff --git a/src/Auxiliaries.lhs b/src/Auxiliaries.lhs
--- a/src/Auxiliaries.lhs
+++ b/src/Auxiliaries.lhs
@@ -4,18 +4,20 @@
 
 %if codeOnly || showModuleHeader
 
+> {-# LANGUAGE TypeSynonymInstances #-}
+> {-# LANGUAGE FlexibleInstances #-}
 > module Auxiliaries            (  module Auxiliaries  )
 > where
 >
 > import Data.Char              (  isSpace  )
+> import Control.Arrow          (  (>>>), Kleisli(..) )
+> import qualified Control.Arrow as A
 > import Control.Monad          (  MonadPlus(..)  )
 > import Control.Monad.Error
 
 %endif
 
-> infixr 9 {-"\;"-} .>  -- same fixity as `|.|'
 > infixr 5 {-"\;"-} <|  -- same fixity as `|:|'
-> infixr 0 {-"\;"-} @@, @>
 
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 \subsubsection{Operations on chars}
@@ -29,6 +31,12 @@
 \subsubsection{Operations on lists}
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
+> splitOn                       :: (Char -> Bool) -> String -> [String]
+> splitOn p s                   =  case dropWhile p s of
+>                                    "" -> []
+>                                    s' -> w : splitOn p s''
+>                                            where (w,s'') = break p s'
+
 > rtake                         :: Int -> [a] -> [a]
 > rtake n                       =  reverse . take n . reverse
 
@@ -67,14 +75,8 @@
 > withoutSpaces                 :: String -> String
 > withoutSpaces s               =  filter (not . isSpace) s
 
-> intersperse                   :: a -> [a] -> [a]
-> intersperse s []              =  []
-> intersperse s (a : as)        =  a : intersperse1 as
->   where intersperse1 []       =  []
->         intersperse1 (a : as) =  s : a : intersperse1 as
-
 > group                         :: Int -> [a] -> [[a]]
-> group n                       =  repSplit (repeat n) .> takeWhile (not . null)
+> group n                       =  repSplit (repeat n) >>> takeWhile (not . null)
 
 > repSplit                      :: [Int] -> [a] -> [[a]]
 > repSplit [] xs                =  []
@@ -88,40 +90,9 @@
 > lift                          :: (Monad m) => (a -> b) -> (a -> m b)
 > lift f a                      =  return (f a)
 
-Kleisli and reverse Kleisli composition.
-
-> (@@)                          :: (Monad m) => (a -> m b) -> (c -> m a) -> c -> m b
-> f @@ g                        =  \a -> g a >>= f
->
-> (@>)                          :: (Monad m) => (a -> m b) -> (b -> m c) -> a -> m c
-> f @> g                        =  \a -> f a >>= g
->
-> (***)                         :: Monad m => (a -> m a') -> (b -> m b') -> (a, b) -> m (a', b')
-> m *** n                       =  \(a, b) -> do { a' <- m a; b' <- n b; return (a', b') }
-
-> many                          :: (MonadPlus m) => m a -> m [a]
-> many m                        =  do { a <- m; as <- many m; return (a : as) }
->                                  `mplus` return []
->
-> optional                      :: (MonadPlus m) => m a -> m (Maybe a)
-> optional m                    =  do { a <- m; return (Just a) }
->                                  `mplus` return Nothing
-
-
-|Either| as an exception monad.
+> (***)                         :: (Monad m) => (a -> m a') -> (b -> m b') -> (a, b) -> m (a', b')
+> f *** g                       =  runKleisli (Kleisli f A.*** Kleisli g)
 
-> {-
-> instance Functor (Either a) where
->     fmap f (Left  a)          =  Left  a
->     fmap f (Right b)          =  Right (f b)
->
-> instance Monad (Either a) where
->     Left  a >>= k             =  Left a
->     Right b >>= k             =  k b
->     return                    =  Right
-> -}
-> instance (Error a, Error b) => Error (a,b) where
->
 > fromRight                     :: Either a b -> b
 > fromRight (Left _)            =  error "fromRight"
 > fromRight (Right b)           =  b
@@ -136,11 +107,12 @@
 > type Message                  =  String
 > type Exc                      =  (Message, String)
 
+> instance Error Exc where
+>   noMsg    = ("unknown error", "")
+>   strMsg s = (s, "")
+
 Reverse Composition.
 
-> (.>)                          :: (a -> b) -> (b -> c) -> a -> c
-> f .> g                        =  \a -> g (f a)
->
 > (<|)                          :: a -> ([a], b) -> ([a], b)
 > a <| (as, b)                  =  (a : as, b)
 >
diff --git a/src/Directives.lhs b/src/Directives.lhs
--- a/src/Directives.lhs
+++ b/src/Directives.lhs
@@ -7,8 +7,10 @@
 > module Directives             (  Formats, parseFormat, Equation, Substs, Subst, parseSubst, Toggles, eval, define, value, nrargs  )
 > where
 >
-> import Data.Char              (  isSpace, isAlpha, isDigit  )
+> import Control.Applicative    (  many, optional )
 > import Control.Monad
+> import Data.Char              (  isSpace, isAlpha, isDigit  )
+> import Data.List
 > import Parser
 > import TeXCommands
 > import TeXParser
@@ -57,12 +59,16 @@
 >                                          _ <- varsym lang "="
 >                                          r <- many item
 >                                          return (string f, (False, [], [], r))
+>                               -- no RHS, try implicit formatting rules
 >                               `mplus` do f <- satisfy isVarid `mplus` satisfy isConid
 >                                          return (string f, (False, [], [], tex f))
 
 \Todo{@%format `div1`@ funktioniert nicht.}
 
 >     where
+>     agda                      =  lang == Agda
+>     tex (Varid s) | agda      =  operator s
+>     tex (Conid s) | agda      =  operator s
 >     tex (Varid s)             =  subscript Varid s
 >     tex (Conid s)             =  subscript Conid s
 >     tex (Qual [] s)           =  tex s
@@ -83,6 +89,13 @@
 >               (t, u)          =  span (== '\'') s'
 >               (v, w)          =  span isDigit u
 
+>     operator s                =  let parts = splitOn (=='_') s
+>                                      start = "_" `isPrefixOf` s
+>                                      end   = "_" `isSuffixOf` s
+>                                  in  (if start then [Varid "_"] else []) ++
+>                                      Data.List.intersperse (Varid "_") (map Varid parts) ++
+>                                      (if end   then [Varid "_"] else [])
+
 ks, 02.02.2004: I have added implicit formatting via |underscore|.
 The above condition should guarantee that it is (almost) only used in 
 cases where previously implicit formatting did not do anything useful.
@@ -136,15 +149,18 @@
 > parseSubst                    :: Lang -> String -> Either Exc (String, Subst)
 > parseSubst lang s             =  parse lang (substitution lang) (convert s)
 >
+> substitution                  :: Lang -> Parser Token (String, Subst)
 > substitution lang             =  do s <- varid
 >                                     args <- many varid
 >                                     _ <- varsym lang "="
 >                                     rhs <- many (satisfy isVarid `mplus` satisfy isTeX)
 >                                     return (s, subst args rhs)
 >   where
+>   subst :: [String] -> [Token] -> Subst
 >   subst args rhs ds           =  catenate (map sub rhs)
 >       where sub (TeX _ d)     =  d
 >             sub (Varid x)     =  FM.fromList (zip args ds) ! x
+> -- TODO: The above lookup can fail badly if unknown variables are used on the rhs of a subst.
 
 \Todo{unbound variables behandeln.}
 ks, 24.10.2008: A bit messy: For Agda, we explicitly exclude "=" from the set
diff --git a/src/FileNameUtils.lhs b/src/FileNameUtils.lhs
--- a/src/FileNameUtils.lhs
+++ b/src/FileNameUtils.lhs
@@ -11,7 +11,7 @@
 >                               , module System.FilePath
 >                               ) where
 >
-> import Prelude hiding         (  catch, readFile )
+> import Prelude
 > import System.IO              (  openFile, IOMode(..), hPutStrLn, stderr,
 >                                  hSetEncoding, hGetContents, utf8, Handle() )
 > import System.IO.Error        (  isDoesNotExistError, isPermissionError )
@@ -19,10 +19,12 @@
 > import System.Environment
 > import Data.List
 > import Control.Monad (filterM)
-> import Control.Exception.Extensible
+> import Control.Exception as E
 >                               (  try, catch, IOException )
 > import System.FilePath
 > import System.Info
+>
+> import Auxiliaries
 
 A searchpath can be added to the front or to the back of the current path
 by pre- or postfixing it with a path separator. Otherwise the new search
@@ -85,15 +87,15 @@
 >                                           else descendFrom s'
 
 > descendFrom                   :: String -> IO [String]
-> descendFrom s                 =  catch (do  d <- getDirectoryContents s
->                                             {- no hidden files, no parents -}
->                                             let d' = map (\x -> s </> x)
->                                                    . filter ((/='.') . head) . filter (not . null) $ d
->                                             d'' <- filterM doesDirectoryExist d'
->                                             d''' <- mapM descendFrom d''
->                                             return (s : concat d''')
->                                        )
->                                        (\ (_ :: IOException) -> return [s])
+> descendFrom s                 =  E.catch (do  d <- getDirectoryContents s
+>                                               {- no hidden files, no parents -}
+>                                               let d' = map (\x -> s </> x)
+>                                                      . filter ((/='.') . head) . filter (not . null) $ d
+>                                               d'' <- filterM doesDirectoryExist d'
+>                                               d''' <- mapM descendFrom d''
+>                                               return (s : concat d''')
+>                                          )
+>                                          (\ (_ :: IOException) -> return [s])
 
 > expandEnvironment             :: String -> IO [String]
 > expandEnvironment s           =  case break (=='{') s of
@@ -107,12 +109,6 @@
 >                                                     (map (\x -> a ++ x ++ o) . splitOn isSearchPathSeparator)
 >                                                     er
 
-> splitOn                       :: (Char -> Bool) -> String -> [String]
-> splitOn p s                   =  case dropWhile p s of
->                                    "" -> []
->                                    s' -> w : splitOn p s''
->                                            where (w,s'') = break p s'
-
 > readTextFile                  :: FilePath -> IO String
 > readTextFile f                =  do h <- openFile f ReadMode
 >                                     hSetEncoding h utf8
@@ -125,7 +121,7 @@
 
 > chaseFile                     :: [String]    {- search path -}
 >                               -> FilePath -> IO (String,FilePath)
-> chaseFile p fn | isAbsolute fn=  catch (t fn) (handle fn (err "."))
+> chaseFile p fn | isAbsolute fn=  E.catch (t fn) (handle fn (err "."))
 >                | p == []      =  chaseFile ["."] fn
 >                | otherwise    =  s $ map (\ d -> md d ++ fn) p
 >   where
@@ -134,7 +130,7 @@
 >         | otherwise           =  addTrailingPathSeparator cs
 >   t f                         =  readTextFile f >>= \x -> return (x,f)
 >   s []                        =  err $ " in search path:\n" ++ showpath
->   s (x:xs)                    =  catch (t x) (handle x (s xs))
+>   s (x:xs)                    =  E.catch (t x) (handle x (s xs))
 >   err extra                   =  ioError
 >                               $  userError $ "File `" ++ fn ++ "' not found or not readable" ++ extra
 >   handle :: FilePath -> IO (String,FilePath) -> IOException -> IO (String,FilePath)
diff --git a/src/HsLexer.lhs b/src/HsLexer.lhs
--- a/src/HsLexer.lhs
+++ b/src/HsLexer.lhs
@@ -4,9 +4,10 @@
 
 %if codeOnly || showModuleHeader
 
+> {-# LANGUAGE NPlusKPatterns #-}
 > module HsLexer                (  module HsLexer ) --Token(..), isVarid, isConid, isNotSpace, string, tokenize  )
 > where
-> import Data.Char 	(  isSpace, isUpper, isLower, isDigit, isAlphaNum, isPunctuation  )
+> import Data.Char      (  isSpace, isUpper, isLower, isDigit, isAlphaNum, isPunctuation  )
 > import qualified Data.Char ( isSymbol )
 > import Control.Monad
 > import Control.Monad.Error ()
@@ -78,7 +79,7 @@
 The main function.
 
 > tokenize                      :: Lang -> String -> Either Exc [Token]
-> tokenize lang                 =  lift tidyup @@ lift qualify @@ lexify lang
+> tokenize lang                 =  lift tidyup <=< lift qualify <=< lexify lang
 
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 \subsubsection{Phase 1}
@@ -110,7 +111,7 @@
 >   | otherwise                 =  return (Comment t, u)
 >   where (d, s') = span (== '-') s
 >         (t, u)  = break (== '\n') s'
-> lex' lang ('{' : '-' : '"' : s) 
+> lex' lang ('{' : '-' : '"' : s)
 >                               =  do let (t, u) = inlineTeX s
 >                                     v <- match "\"-}" u
 >                                     return (TeX True (Text t), v)
@@ -146,7 +147,7 @@
 >                                     (ds, u) <- lexDigits' t
 >                                     (e, v)  <- lexExp u
 >                                     return ('.' : ds ++ e, v)
->                               `mplus` Just ("", s)
+>                               `mplus` lexExp s
 >
 > lexExp                        :: String -> Maybe (String, String)
 > lexExp (e:s)
diff --git a/src/License.lhs b/src/License.lhs
new file mode 100644
--- /dev/null
+++ b/src/License.lhs
@@ -0,0 +1,363 @@
+
+> module License
+> where
+
+> import Version
+
+GPL-related program information
+
+> programInfo                   :: String
+> programInfo                   =
+>     "lhs2TeX " ++ version ++ ", Copyright (C) 1997-2011 Ralf Hinze, Andres Loeh\n\n\
+>     \lhs2TeX comes with ABSOLUTELY NO WARRANTY;\n\
+>     \for details type `lhs2TeX --warranty'.\n\
+>     \This is free software, and you are welcome to redistribute it\n\
+>     \under certain conditions; type `lhs2TeX --copying' for details."
+
+> copying                       :: String
+> copying                       =
+>     "\t\t    GNU GENERAL PUBLIC LICENSE\n\
+>     \\t\t       Version 2, June 1991\n\
+>     \\n\
+>     \ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
+>     \                          59 Temple Place - Suite 330\n\
+>     \                          Boston, MA 02111-1307, USA.\n\
+>     \ Everyone is permitted to copy and distribute verbatim copies\n\
+>     \ of this license document, but changing it is not allowed.\n\
+>     \\n\
+>     \\t\t\t    Preamble\n\
+>     \\n\
+>     \  The licenses for most software are designed to take away your\n\
+>     \freedom to share and change it.  By contrast, the GNU General Public\n\
+>     \License is intended to guarantee your freedom to share and change free\n\
+>     \software--to make sure the software is free for all its users.  This\n\
+>     \General Public License applies to most of the Free Software\n\
+>     \Foundation's software and to any other program whose authors commit to\n\
+>     \using it.  (Some other Free Software Foundation software is covered by\n\
+>     \the GNU Library General Public License instead.)  You can apply it to\n\
+>     \your programs, too.\n\
+>     \\n\
+>     \  When we speak of free software, we are referring to freedom, not\n\
+>     \price.  Our General Public Licenses are designed to make sure that you\n\
+>     \have the freedom to distribute copies of free software (and charge for\n\
+>     \this service if you wish), that you receive source code or can get it\n\
+>     \if you want it, that you can change the software or use pieces of it\n\
+>     \in new free programs; and that you know you can do these things.\n\
+>     \\n\
+>     \  To protect your rights, we need to make restrictions that forbid\n\
+>     \anyone to deny you these rights or to ask you to surrender the rights.\n\
+>     \These restrictions translate to certain responsibilities for you if you\n\
+>     \distribute copies of the software, or if you modify it.\n\
+>     \\n\
+>     \  For example, if you distribute copies of such a program, whether\n\
+>     \gratis or for a fee, you must give the recipients all the rights that\n\
+>     \you have.  You must make sure that they, too, receive or can get the\n\
+>     \source code.  And you must show them these terms so they know their\n\
+>     \rights.\n\
+>     \\n\
+>     \  We protect your rights with two steps: (1) copyright the software, and\n\
+>     \(2) offer you this license which gives you legal permission to copy,\n\
+>     \distribute and/or modify the software.\n\
+>     \\n\
+>     \  Also, for each author's protection and ours, we want to make certain\n\
+>     \that everyone understands that there is no warranty for this free\n\
+>     \software.  If the software is modified by someone else and passed on, we\n\
+>     \want its recipients to know that what they have is not the original, so\n\
+>     \that any problems introduced by others will not reflect on the original\n\
+>     \authors' reputations.\n\
+>     \\n\
+>     \  Finally, any free program is threatened constantly by software\n\
+>     \patents.  We wish to avoid the danger that redistributors of a free\n\
+>     \program will individually obtain patent licenses, in effect making the\n\
+>     \program proprietary.  To prevent this, we have made it clear that any\n\
+>     \patent must be licensed for everyone's free use or not licensed at all.\n\
+>     \\n\
+>     \  The precise terms and conditions for copying, distribution and\n\
+>     \modification follow.\n\
+>     \\f\n\
+>     \\t\t    GNU GENERAL PUBLIC LICENSE\n\
+>     \   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
+>     \\n\
+>     \  0. This License applies to any program or other work which contains\n\
+>     \a notice placed by the copyright holder saying it may be distributed\n\
+>     \under the terms of this General Public License.  The \"Program\", below,\n\
+>     \refers to any such program or work, and a \"work based on the Program\"\n\
+>     \means either the Program or any derivative work under copyright law:\n\
+>     \that is to say, a work containing the Program or a portion of it,\n\
+>     \either verbatim or with modifications and/or translated into another\n\
+>     \language.  (Hereinafter, translation is included without limitation in\n\
+>     \the term \"modification\".)  Each licensee is addressed as \"you\".\n\
+>     \\n\
+>     \Activities other than copying, distribution and modification are not\n\
+>     \covered by this License; they are outside its scope.  The act of\n\
+>     \running the Program is not restricted, and the output from the Program\n\
+>     \is covered only if its contents constitute a work based on the\n\
+>     \Program (independent of having been made by running the Program).\n\
+>     \Whether that is true depends on what the Program does.\n\
+>     \\n\
+>     \  1. You may copy and distribute verbatim copies of the Program's\n\
+>     \source code as you receive it, in any medium, provided that you\n\
+>     \conspicuously and appropriately publish on each copy an appropriate\n\
+>     \copyright notice and disclaimer of warranty; keep intact all the\n\
+>     \notices that refer to this License and to the absence of any warranty;\n\
+>     \and give any other recipients of the Program a copy of this License\n\
+>     \along with the Program.\n\
+>     \\n\
+>     \You may charge a fee for the physical act of transferring a copy, and\n\
+>     \you may at your option offer warranty protection in exchange for a fee.\n\
+>     \\n\
+>     \  2. You may modify your copy or copies of the Program or any portion\n\
+>     \of it, thus forming a work based on the Program, and copy and\n\
+>     \distribute such modifications or work under the terms of Section 1\n\
+>     \above, provided that you also meet all of these conditions:\n\
+>     \\n\
+>     \    a) You must cause the modified files to carry prominent notices\n\
+>     \    stating that you changed the files and the date of any change.\n\
+>     \\n\
+>     \    b) You must cause any work that you distribute or publish, that in\n\
+>     \    whole or in part contains or is derived from the Program or any\n\
+>     \    part thereof, to be licensed as a whole at no charge to all third\n\
+>     \    parties under the terms of this License.\n\
+>     \\n\
+>     \    c) If the modified program normally reads commands interactively\n\
+>     \    when run, you must cause it, when started running for such\n\
+>     \    interactive use in the most ordinary way, to print or display an\n\
+>     \    announcement including an appropriate copyright notice and a\n\
+>     \    notice that there is no warranty (or else, saying that you provide\n\
+>     \    a warranty) and that users may redistribute the program under\n\
+>     \    these conditions, and telling the user how to view a copy of this\n\
+>     \    License.  (Exception: if the Program itself is interactive but\n\
+>     \    does not normally print such an announcement, your work based on\n\
+>     \    the Program is not required to print an announcement.)\n\
+>     \\f\n\
+>     \These requirements apply to the modified work as a whole.  If\n\
+>     \identifiable sections of that work are not derived from the Program,\n\
+>     \and can be reasonably considered independent and separate works in\n\
+>     \themselves, then this License, and its terms, do not apply to those\n\
+>     \sections when you distribute them as separate works.  But when you\n\
+>     \distribute the same sections as part of a whole which is a work based\n\
+>     \on the Program, the distribution of the whole must be on the terms of\n\
+>     \this License, whose permissions for other licensees extend to the\n\
+>     \entire whole, and thus to each and every part regardless of who wrote it.\n\
+>     \\n\
+>     \Thus, it is not the intent of this section to claim rights or contest\n\
+>     \your rights to work written entirely by you; rather, the intent is to\n\
+>     \exercise the right to control the distribution of derivative or\n\
+>     \collective works based on the Program.\n\
+>     \\n\
+>     \In addition, mere aggregation of another work not based on the Program\n\
+>     \with the Program (or with a work based on the Program) on a volume of\n\
+>     \a storage or distribution medium does not bring the other work under\n\
+>     \the scope of this License.\n\
+>     \\n\
+>     \  3. You may copy and distribute the Program (or a work based on it,\n\
+>     \under Section 2) in object code or executable form under the terms of\n\
+>     \Sections 1 and 2 above provided that you also do one of the following:\n\
+>     \\n\
+>     \    a) Accompany it with the complete corresponding machine-readable\n\
+>     \    source code, which must be distributed under the terms of Sections\n\
+>     \    1 and 2 above on a medium customarily used for software interchange; or,\n\
+>     \\n\
+>     \    b) Accompany it with a written offer, valid for at least three\n\
+>     \    years, to give any third party, for a charge no more than your\n\
+>     \    cost of physically performing source distribution, a complete\n\
+>     \    machine-readable copy of the corresponding source code, to be\n\
+>     \    distributed under the terms of Sections 1 and 2 above on a medium\n\
+>     \    customarily used for software interchange; or,\n\
+>     \\n\
+>     \    c) Accompany it with the information you received as to the offer\n\
+>     \    to distribute corresponding source code.  (This alternative is\n\
+>     \    allowed only for noncommercial distribution and only if you\n\
+>     \    received the program in object code or executable form with such\n\
+>     \    an offer, in accord with Subsection b above.)\n\
+>     \\n\
+>     \The source code for a work means the preferred form of the work for\n\
+>     \making modifications to it.  For an executable work, complete source\n\
+>     \code means all the source code for all modules it contains, plus any\n\
+>     \associated interface definition files, plus the scripts used to\n\
+>     \control compilation and installation of the executable.  However, as a\n\
+>     \special exception, the source code distributed need not include\n\
+>     \anything that is normally distributed (in either source or binary\n\
+>     \form) with the major components (compiler, kernel, and so on) of the\n\
+>     \operating system on which the executable runs, unless that component\n\
+>     \itself accompanies the executable.\n\
+>     \\n\
+>     \If distribution of executable or object code is made by offering\n\
+>     \access to copy from a designated place, then offering equivalent\n\
+>     \access to copy the source code from the same place counts as\n\
+>     \distribution of the source code, even though third parties are not\n\
+>     \compelled to copy the source along with the object code.\n\
+>     \\f\n\
+>     \  4. You may not copy, modify, sublicense, or distribute the Program\n\
+>     \except as expressly provided under this License.  Any attempt\n\
+>     \otherwise to copy, modify, sublicense or distribute the Program is\n\
+>     \void, and will automatically terminate your rights under this License.\n\
+>     \However, parties who have received copies, or rights, from you under\n\
+>     \this License will not have their licenses terminated so long as such\n\
+>     \parties remain in full compliance.\n\
+>     \\n\
+>     \  5. You are not required to accept this License, since you have not\n\
+>     \signed it.  However, nothing else grants you permission to modify or\n\
+>     \distribute the Program or its derivative works.  These actions are\n\
+>     \prohibited by law if you do not accept this License.  Therefore, by\n\
+>     \modifying or distributing the Program (or any work based on the\n\
+>     \Program), you indicate your acceptance of this License to do so, and\n\
+>     \all its terms and conditions for copying, distributing or modifying\n\
+>     \the Program or works based on it.\n\
+>     \\n\
+>     \  6. Each time you redistribute the Program (or any work based on the\n\
+>     \Program), the recipient automatically receives a license from the\n\
+>     \original licensor to copy, distribute or modify the Program subject to\n\
+>     \these terms and conditions.  You may not impose any further\n\
+>     \restrictions on the recipients' exercise of the rights granted herein.\n\
+>     \You are not responsible for enforcing compliance by third parties to\n\
+>     \this License.\n\
+>     \\n\
+>     \  7. If, as a consequence of a court judgment or allegation of patent\n\
+>     \infringement or for any other reason (not limited to patent issues),\n\
+>     \conditions are imposed on you (whether by court order, agreement or\n\
+>     \otherwise) that contradict the conditions of this License, they do not\n\
+>     \excuse you from the conditions of this License.  If you cannot\n\
+>     \distribute so as to satisfy simultaneously your obligations under this\n\
+>     \License and any other pertinent obligations, then as a consequence you\n\
+>     \may not distribute the Program at all.  For example, if a patent\n\
+>     \license would not permit royalty-free redistribution of the Program by\n\
+>     \all those who receive copies directly or indirectly through you, then\n\
+>     \the only way you could satisfy both it and this License would be to\n\
+>     \refrain entirely from distribution of the Program.\n\
+>     \\n\
+>     \If any portion of this section is held invalid or unenforceable under\n\
+>     \any particular circumstance, the balance of the section is intended to\n\
+>     \apply and the section as a whole is intended to apply in other\n\
+>     \circumstances.\n\
+>     \\n\
+>     \It is not the purpose of this section to induce you to infringe any\n\
+>     \patents or other property right claims or to contest validity of any\n\
+>     \such claims; this section has the sole purpose of protecting the\n\
+>     \integrity of the free software distribution system, which is\n\
+>     \implemented by public license practices.  Many people have made\n\
+>     \generous contributions to the wide range of software distributed\n\
+>     \through that system in reliance on consistent application of that\n\
+>     \system; it is up to the author/donor to decide if he or she is willing\n\
+>     \to distribute software through any other system and a licensee cannot\n\
+>     \impose that choice.\n\
+>     \\n\
+>     \This section is intended to make thoroughly clear what is believed to\n\
+>     \be a consequence of the rest of this License.\n\
+>     \\f\n\
+>     \  8. If the distribution and/or use of the Program is restricted in\n\
+>     \certain countries either by patents or by copyrighted interfaces, the\n\
+>     \original copyright holder who places the Program under this License\n\
+>     \may add an explicit geographical distribution limitation excluding\n\
+>     \those countries, so that distribution is permitted only in or among\n\
+>     \countries not thus excluded.  In such case, this License incorporates\n\
+>     \the limitation as if written in the body of this License.\n\
+>     \\n\
+>     \  9. The Free Software Foundation may publish revised and/or new versions\n\
+>     \of the General Public License from time to time.  Such new versions will\n\
+>     \be similar in spirit to the present version, but may differ in detail to\n\
+>     \address new problems or concerns.\n\
+>     \\n\
+>     \Each version is given a distinguishing version number.  If the Program\n\
+>     \specifies a version number of this License which applies to it and \"any\n\
+>     \later version\", you have the option of following the terms and conditions\n\
+>     \either of that version or of any later version published by the Free\n\
+>     \Software Foundation.  If the Program does not specify a version number of\n\
+>     \this License, you may choose any version ever published by the Free Software\n\
+>     \Foundation.\n\
+>     \\n\
+>     \  10. If you wish to incorporate parts of the Program into other free\n\
+>     \programs whose distribution conditions are different, write to the author\n\
+>     \to ask for permission.  For software which is copyrighted by the Free\n\
+>     \Software Foundation, write to the Free Software Foundation; we sometimes\n\
+>     \make exceptions for this.  Our decision will be guided by the two goals\n\
+>     \of preserving the free status of all derivatives of our free software and\n\
+>     \of promoting the sharing and reuse of software generally.\n\
+>     \\n"
+>     ++ warranty ++
+>     "\n\n\
+>     \\t\t     END OF TERMS AND CONDITIONS\n\
+>     \\f\n\
+>     \\t    How to Apply These Terms to Your New Programs\n\
+>     \\n\
+>     \  If you develop a new program, and you want it to be of the greatest\n\
+>     \possible use to the public, the best way to achieve this is to make it\n\
+>     \free software which everyone can redistribute and change under these terms.\n\
+>     \\n\
+>     \  To do so, attach the following notices to the program.  It is safest\n\
+>     \to attach them to the start of each source file to most effectively\n\
+>     \convey the exclusion of warranty; and each file should have at least\n\
+>     \the \"copyright\" line and a pointer to where the full notice is found.\n\
+>     \\n\
+>     \    <one line to give the program's name and a brief idea of what it does.>\n\
+>     \    Copyright (C) 19yy  <name of author>\n\
+>     \\n\
+>     \    This program is free software; you can redistribute it and/or modify\n\
+>     \    it under the terms of the GNU General Public License as published by\n\
+>     \    the Free Software Foundation; either version 2 of the License, or\n\
+>     \    (at your option) any later version.\n\
+>     \\n\
+>     \    This program is distributed in the hope that it will be useful,\n\
+>     \    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+>     \    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
+>     \    GNU General Public License for more details.\n\
+>     \\n\
+>     \    You should have received a copy of the GNU General Public License\n\
+>     \    along with this program; see the file COPYING.  If not, write to\n\
+>     \    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n\
+>     \    Boston, MA 02111-1307, USA.\n\
+>     \\n\
+>     \Also add information on how to contact you by electronic and paper mail.\n\
+>     \\n\
+>     \If the program is interactive, make it output a short notice like this\n\
+>     \when it starts in an interactive mode:\n\
+>     \\n\
+>     \    Gnomovision version 69, Copyright (C) 19yy name of author\n\
+>     \    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n\
+>     \    This is free software, and you are welcome to redistribute it\n\
+>     \    under certain conditions; type `show c' for details.\n\
+>     \\n\
+>     \The hypothetical commands `show w' and `show c' should show the appropriate\n\
+>     \parts of the General Public License.  Of course, the commands you use may\n\
+>     \be called something other than `show w' and `show c'; they could even be\n\
+>     \mouse-clicks or menu items--whatever suits your program.\n\
+>     \\n\
+>     \You should also get your employer (if you work as a programmer) or your\n\
+>     \school, if any, to sign a \"copyright disclaimer\" for the program, if\n\
+>     \necessary.  Here is a sample; alter the names:\n\
+>     \\n\
+>     \  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n\
+>     \  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\
+>     \\n\
+>     \  <signature of Ty Coon>, 1 April 1989\n\
+>     \  Ty Coon, President of Vice\n\
+>     \\n\
+>     \This General Public License does not permit incorporating your program into\n\
+>     \proprietary programs.  If your program is a subroutine library, you may\n\
+>     \consider it more useful to permit linking proprietary applications with the\n\
+>     \library.  If this is what you want to do, use the GNU Library General\n\
+>     \Public License instead of this License."
+
+> warranty                      :: String
+> warranty                      =
+>     "\t\t\t    NO WARRANTY\n\
+>     \\n\
+>     \  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
+>     \FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n\
+>     \OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
+>     \PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
+>     \OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
+>     \MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n\
+>     \TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n\
+>     \PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
+>     \REPAIR OR CORRECTION.\n\
+>     \\n\
+>     \  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
+>     \WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
+>     \REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
+>     \INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
+>     \OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
+>     \TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
+>     \YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
+>     \PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
+>     \POSSIBILITY OF SUCH DAMAGES."
diff --git a/src/Main.lhs b/src/Main.lhs
--- a/src/Main.lhs
+++ b/src/Main.lhs
@@ -16,11 +16,14 @@
 > import System.Environment
 > import System.Exit
 > import System.Process
-> import Version
+> import Control.Arrow
 > import Control.Monad
+> import Control.Monad.Error
+> import Control.Monad.State ( MonadState(..), modify )
+> import Control.Monad.Trans
 > import Prelude hiding ( getContents )
 >
-> -- import IOExts
+> import Version
 > import TeXCommands
 > import TeXParser
 > import qualified Verbatim
@@ -30,10 +33,12 @@
 > import qualified NewCode
 > import Directives
 > import Document
+> import State
 > import StateT
 > import qualified FiniteMap as FM
 > import Auxiliaries
 > import Value
+> import License
 >
 > import FileNameUtils
 > --import Directory
@@ -52,7 +57,7 @@
 >   (o,n,[])                    -> do hSetEncoding stdin  utf8
 >                                     hSetEncoding stdout utf8
 >                                     hSetEncoding stderr utf8
->                                     (flags,initdirs,styles) 
+>                                     (flags,initdirs,styles)
 >                                        <- foldM (\(s,d,x) (sf,df,ns) -> do s' <- sf s
 >                                                                            return (s',df d,ns ++ x))
 >                                                 (state0,[],[]) o
@@ -82,76 +87,12 @@
 
 > type Formatter                =  XIO Exc State ()
 
-State.
-
-> type CondInfo                 =  (FilePath, LineNo, Bool, Bool)
-
-> data State                    =  State { style      :: Style,
->                                          lang       :: Lang,          -- Haskell or Agda, currently
->                                          verbose    :: Bool,
->                                          searchpath :: [FilePath],
->                                          file       :: FilePath,      -- also used for `hugs'
->                                          lineno     :: LineNo,
->                                          ofile      :: FilePath,
->                                          olineno    :: LineNo,
->                                          atnewline  :: Bool,
->                                          fldir      :: Bool,          -- file/linenumber directives
->                                          pragmas    :: Bool,          -- generate LINE pragmas?
->                                          output     :: Handle,
->                                          opts       :: String,        -- options for `hugs'
->                                          files      :: [(FilePath, LineNo)], -- includees (?)
->                                          path       :: FilePath,      -- for relative includes
->                                          fmts       :: Formats,
->                                          subst      :: Substs,
->                                          stack      :: [Formats],     -- for grouping
->                                          toggles    :: Toggles,       -- @%let@ defined toggles
->                                          conds      :: [CondInfo],    -- for conditional directives
->                                          align      :: Maybe Int,     -- math: internal alignment column
->                                          stacks     :: (Math.Stack, Math.Stack),      -- math: indentation stacks
->                                          separation :: Int,           -- poly: separation
->                                          latency    :: Int,           -- poly: latency
->                                          pstack     :: Poly.Stack,    -- poly: indentation stack
->                                          externals  :: Externals      -- handles for external processes (hugs,ghci)
->                                        }
-
-Initial state.
-
-> state0                        :: State
-> state0                        =  State { lang       = Haskell,
->                                          verbose    = False,
->                                          searchpath = searchPath,
->                                          lineno     = 0,
->                                          olineno    = 0,
->                                          atnewline  = True,
->                                          fldir      = False,
->                                          pragmas    = True,
->                                          output     = stdout,
->                                          opts       = "",
->                                          files      = [],
->                                          path       = "",
->                                          fmts       = FM.empty,
->                                          subst      = FM.empty,
->                                          stack      = [],
->                                          conds      = [],
->                                          align      = Nothing,
->                                          stacks     = ([], []),
->                                          separation = 2,
->                                          latency    = 2,
->                                          pstack     = [],
->                                          -- ks, 03.01.04: added to prevent warnings during compilation
->                                          style      = error "uninitialized style",
->                                          file       = error "uninitialized filename",
->                                          ofile      = error "uninitialized filename",
->                                          toggles    = error "uninitialized toggles",
->                                          externals  = FM.empty
->                                        }
-
 > initState                     :: Style -> FilePath -> [FilePath] -> State -> State
-> initState sty filePath ep s   =  s { style = sty, 
+> initState sty filePath ep s   =  s { style = sty,
 >                                      file = filePath,
 >                                      ofile = filePath,
 >                                      searchpath = ep,
->                                      toggles = FM.fromList toggles0 
+>                                      toggles = FM.fromList toggles0
 >                                    }
 >     where toggles0            =  --[(decode CodeOnly, Bool (sty == CodeOnly))]
 >                                  [("style", Int (fromEnum sty))]
@@ -182,8 +123,8 @@
 > lhs2TeX                       :: Style -> State -> [Class] -> [String] -> IO ()
 > lhs2TeX s flags dirs files    =  do (str, file) <- input files
 >                                     expandedpath <- expandPath (searchpath flags)
->                                     toIO (do store (initState s file expandedpath flags)
->                                              formats (map (No 0) dirs) `handle` abort
+>                                     toIO (do put (initState s file expandedpath flags)
+>                                              formats (map (No 0) dirs) `catchError` abort
 >                                              formatStr (addEndEOF str)
 >                                              stopexternals)
 >   where   addEndEOF           =  (++"%EOF\n") . unlines . lines
@@ -232,7 +173,7 @@
 >   , Option ['l'] ["let"]     (ReqArg (\s -> (return, (Directive Let s:), [])) "equation") "assume <equation>"
 >   , Option ['s'] ["set"]     (ReqArg (\s -> (return, (Directive Let (s ++ " = True"):), [])) "flag")  "set <flag>"
 >   , Option ['u'] ["unset"]   (ReqArg (\s -> (return, (Directive Let (s ++ " = False"):), [])) "flag") "unset <flag>"
->   , Option ['P'] ["path"]    (ReqArg (\p -> (\s -> return $ s { searchpath = modifySearchPath (searchpath s) p }, id , [])) "path") 
+>   , Option ['P'] ["path"]    (ReqArg (\p -> (\s -> return $ s { searchpath = modifySearchPath (searchpath s) p }, id , [])) "path")
 >                                                                                       "modify search path"
 >   , Option []    ["searchpath"]
 >                              (NoArg (return, id, [SearchPath]))                           "show searchpath"
@@ -241,7 +182,7 @@
 >   ]
 >
 > formatStr                     :: String -> Formatter
-> formatStr str                 =  formats (texparse 1 str) `handle` abort
+> formatStr str                 =  formats (texparse 1 str) `catchError` abort
 
 Compatibility mode option handling.
 
@@ -269,9 +210,9 @@
 We abort immediately if an error has occured.
 
 > abort                         :: Exc -> Formatter
-> abort (msg, context)          =  do st <- fetch
->                                     fromIO (hPutStrLn stderr (text st))
->                                     fromIO (exitWith (ExitFailure 1))
+> abort (msg, context)          =  do st <- get
+>                                     liftIO (hPutStrLn stderr (text st))
+>                                     liftIO (exitWith (ExitFailure 1))
 >     where text st             =  "*** Error in " ++ at (file st) (lineno st) ++ ": \n"
 >                               ++ unlines [ "included from " ++ at f l | (f, l) <- files st ]
 >                               ++ msg ++ "\n"
@@ -285,12 +226,12 @@
 > formats                       :: [Numbered Class] -> Formatter
 > formats []                    =  return ()
 > formats (No n  (Directive d s) : ts)
->     | conditional d           =  do update (\st -> st{lineno = n})
->                                     st <- fetch
+>     | conditional d           =  do modify (\st -> st{lineno = n})
+>                                     st <- get
 >                                     directive (lang st)
->                                               d s (file st,n) 
+>                                               d s (file st,n)
 >                                               (conds st) (toggles st) ts
-> formats (No n t : ts)         =  do update (\st -> st{lineno = n})
+> formats (No n t : ts)         =  do modify (\st -> st{lineno = n})
 >                                     format t
 >                                     formats ts
 
@@ -300,26 +241,26 @@
 > format (Inline s)             =  inline s
 > format (Command Hs s)         =  inline s
 > format (Command (Vrb b) s)    =  out (Verbatim.inline b s)
-> format (Command Eval s)       =  do st <- fetch
+> format (Command Eval s)       =  do st <- get
 >                                     unless (style st `elem` [CodeOnly,NewCode]) $
 >                                       do result <- external (map unNL s)
 >                                          inline result
-> format (Command Perform s)    =  do st <- fetch
+> format (Command Perform s)    =  do st <- get
 >                                     unless (style st `elem` [CodeOnly,NewCode]) $
 >                                       do result <- external (map unNL s)
->                                          update (\st@State{file = f', lineno = l'} ->
+>                                          modify (\st@State{file = f', lineno = l'} ->
 >                                                    st{file = "<perform>", files = (f', l') : files st})
->                                          fromIO (when (verbose st) (hPutStr stderr $ "(" ++ "<perform>"))
+>                                          liftIO (when (verbose st) (hPutStr stderr $ "(" ++ "<perform>"))
 >                                          formatStr (addEndNL result)
->                                          update (\st'@State{files = (f, l) : fs} ->
+>                                          modify (\st'@State{files = (f, l) : fs} ->
 >                                                    st'{file = f, lineno = l, files = fs})
->                                          fromIO (when (verbose st) (hPutStrLn stderr $ ")"))
+>                                          liftIO (when (verbose st) (hPutStrLn stderr $ ")"))
 >     where
 >     addEndNL                  =  (++"\n") . unlines . lines
 
 Remove trailing blank line.
 
->     trim                      =  reverse .> skip .> reverse
+>     trim                      =  reverse >>> skip >>> reverse
 >
 >     skip s | all isSpace t    =  u
 >            | otherwise        =  s
@@ -328,11 +269,11 @@
 > format (Environment Haskell_ s)
 >                               =  display s
 > format (Environment Code s)   =  display s
-> format (Environment Spec s)   =  do st <- fetch
+> format (Environment Spec s)   =  do st <- get
 >                                     unless (style st `elem` [CodeOnly,NewCode]) $
 >                                       display s
 > format (Environment Evaluate s)
->                               =  do st <- fetch
+>                               =  do st <- get
 >                                     unless (style st `elem` [CodeOnly,NewCode]) $
 >                                       do result <- external s
 >                                          display result
@@ -340,27 +281,27 @@
 > format (Environment Ignore s) =  return ()
 > format (Environment (Verbatim b) s)
 >                               =  out (Verbatim.display 120 b s)
-> format (Directive Format s)   =  do st <- fetch
+> format (Directive Format s)   =  do st <- get
 >                                     b@(n,e) <- fromEither (parseFormat (lang st) s)
->                                     store (st{fmts = FM.add b (fmts st)})
-> format (Directive Subst s)    =  do st <- fetch
+>                                     put (st{fmts = FM.add b (fmts st)})
+> format (Directive Subst s)    =  do st <- get
 >                                     b <- fromEither (parseSubst (lang st) s)
->                                     store (st{subst = FM.add b (subst st)})
-> format (Directive Include arg)=  do st <- fetch
+>                                     put (st{subst = FM.add b (subst st)})
+> format (Directive Include arg)=  do st <- get
 >                                     let d  = path st
 >                                     let sp = searchpath st
->                                     update (\st@State{file = f', lineno = l'} ->
+>                                     modify (\st@State{file = f', lineno = l'} ->
 >                                         st{file = f, files = (f', l') : files st, path = d ++ dir f})
->                                     -- |d <- fromIO getCurrentDirectory|
->                                     -- |fromIO (setCurrentDirectory (dir f))|
->                                     (str,f) <- fromIO (chaseFile sp (d ++ f))
->                                     update (\st -> st { file = f })
->                                     fromIO (when (verbose st) (hPutStr stderr $ "(" ++ f))
+>                                     -- |d <- liftIO getCurrentDirectory|
+>                                     -- |liftIO (setCurrentDirectory (dir f))|
+>                                     (str,f) <- liftIO (chaseFile sp (d ++ f))
+>                                     modify (\st -> st { file = f })
+>                                     liftIO (when (verbose st) (hPutStr stderr $ "(" ++ f))
 >                                     formatStr (addEndNL str)
->                                     -- |fromIO (setCurrentDirectory d)|
->                                     update (\st'@State{files = (f, l) : fs} ->
+>                                     -- |liftIO (setCurrentDirectory d)|
+>                                     modify (\st'@State{files = (f, l) : fs} ->
 >                                         st'{file = f, lineno = l, files = fs, path = d})
->                                     fromIO (when (verbose st) (hPutStrLn stderr $ ")"))
+>                                     liftIO (when (verbose st) (hPutStrLn stderr $ ")"))
 >     where f                   =  withoutSpaces arg
 >           addEndNL            =  (++"\n") . unlines . lines
 
@@ -378,24 +319,24 @@
 more, as a double newline is interpreted as a \par by TeX, and that might 
 also not be desired.
 
-> format (Directive Begin _)    =  update (\st -> st{stack = fmts st : stack st})
-> format (Directive End _)      =  do st <- fetch
+> format (Directive Begin _)    =  modify (\st -> st{stack = fmts st : stack st})
+> format (Directive End _)      =  do st <- get
 >                                     when (null (stack st)) $
->                                       do fromIO (hPutStrLn stderr $ "unbalanced %} in line " 
+>                                       do liftIO (hPutStrLn stderr $ "unbalanced %} in line "
 >                                                                       ++ show (lineno st))
->                                          update (\st -> st{stack = [fmts st]})
->                                     update (\st@State{stack = d:ds} -> st{fmts = d, stack = ds})
+>                                          modify (\st -> st{stack = [fmts st]})
+>                                     modify (\st@State{stack = d:ds} -> st{fmts = d, stack = ds})
 
 ks, 11.09.03: added exception handling for unbalanced grouping
 
 \Todo{|toggles| should be saved, as well.}
 
-> format (Directive Let s)      =  do st <- fetch
+> format (Directive Let s)      =  do st <- get
 >                                     t <- fromEither (define (lang st) (toggles st) s)
->                                     store st{toggles = FM.add t (toggles st)}
+>                                     put st{toggles = FM.add t (toggles st)}
 > format (Directive Align s)
->     | all isSpace s           =  update (\st -> st{align = Nothing, stacks  = ([], [])})
->     | otherwise               =  update (\st -> st{align = Just (read s), stacks  = ([], [])})
+>     | all isSpace s           =  modify (\st -> st{align = Nothing, stacks  = ([], [])})
+>     | otherwise               =  modify (\st -> st{align = Just (read s), stacks  = ([], [])})
 
 \NB @%align@ also resets the left identation stacks.
 
@@ -403,14 +344,14 @@
 the corresponding indentation stack |pstack|.
 
 > format (Directive Separation s )
->                               =  update (\st -> st{separation = read s, pstack = []})
-> format (Directive Latency s)  =  update (\st -> st{latency = read s, pstack = []})  
+>                               =  modify (\st -> st{separation = read s, pstack = []})
+> format (Directive Latency s)  =  modify (\st -> st{latency = read s, pstack = []})
 
-> format (Directive File s)     =  update (\st -> st{file = withoutSpaces s})
-> format (Directive Options s)  =  update (\st -> st{opts = trim s})
->     where trim                =  dropWhile isSpace .> reverse .> dropWhile isSpace .> reverse
+> format (Directive File s)     =  modify (\st -> st{file = withoutSpaces s})
+> format (Directive Options s)  =  modify (\st -> st{opts = trim s})
+>     where trim                =  dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
 
-> format (Error exc)            =  raise exc
+> format (Error exc)            =  throwError exc
 
 Printing documents.
 %{
@@ -419,14 +360,14 @@
 
 > eject                         :: Doc -> Formatter
 > eject Empty                   =  return ()
-> eject (Text s)                =  do  st <- fetch
+> eject (Text s)                =  do  st <- get
 >                                      let (ls,enl) = checkNLs 0 s
 >                                      when (fldir st && not (null s) && atnewline st && (ofile st /= file st || olineno st /= lineno st)) $
->                                        do  fromIO (hPutStr (output st) ("%file " ++ show (lineno st) ++ " " ++ show (file st) ++ "\n"))
->                                            store (st { ofile = file st, olineno = lineno st })
->                                            
->                                      fromIO (hPutStr (output st) s)
->                                      update (\st -> st { olineno = olineno st + ls, atnewline = enl (atnewline st)})
+>                                        do  liftIO (hPutStr (output st) ("%file " ++ show (lineno st) ++ " " ++ show (file st) ++ "\n"))
+>                                            put (st { ofile = file st, olineno = lineno st })
+>
+>                                      liftIO (hPutStr (output st) s)
+>                                      modify (\st -> st { olineno = olineno st + ls, atnewline = enl (atnewline st)})
 >     where
 >     checkNLs n ('\n':[])      =  (n+1,const True)
 >     checkNLs n (_:[])         =  (n,const False)
@@ -435,10 +376,10 @@
 >     checkNLs n (_:xs)         =  checkNLs n xs
 > eject (d1 :^: d2)             =  eject d1 >> eject d2
 > eject (Embedded s)            =  formatStr s
-> eject (Sub s ds)              =  do st <- fetch; substitute (subst st)
+> eject (Sub s ds)              =  do st <- get; substitute (subst st)
 >     where
 >     substitute d              =  case FM.lookup s d of
->         Nothing               -> raise (undef s, "")
+>         Nothing               -> throwError (undef s, "")
 >         Just sub              -> eject (sub ds)
 >
 > undef                         :: String -> String
@@ -452,13 +393,13 @@
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
 > out                           :: Doc -> Formatter
-> out d                         =  do st <- fetch; eject (select (style st))
+> out d                         =  do st <- get; eject (select (style st))
 >     where select CodeOnly     =  Empty
 >           select NewCode      =  Empty
 >           select _            =  d
 
 > inline, display               :: String -> Formatter
-> inline s                      =  do st <- fetch
+> inline s                      =  do st <- get
 >                                     d <- fromEither (select (style st) st)
 >                                     eject d
 >   where select Verb st        =  Right (Verbatim.inline False s)
@@ -468,9 +409,9 @@
 >         select CodeOnly st    =  return Empty
 >         select NewCode st     =  return Empty   -- generate PRAGMA or something?
 
-> display s                     =  do st <- fetch
+> display s                     =  do st <- get
 >                                     (d, st') <- fromEither (select (style st) st)
->                                     store st'
+>                                     put st'
 >                                     eject d
 >   where select Verb st        =  return (Verbatim.display 120 False s, st)
 >         select Typewriter st  =  do d <- Typewriter.display (lang st) (fmts st) s; return (d, st)
@@ -489,7 +430,7 @@
 Delete leading and trailing blank line (only the first!).
 
 > trim                          :: String -> String
-> trim                          =  skip .> reverse .> skip .> reverse
+> trim                          =  skip >>> reverse >>> skip >>> reverse
 >     where
 >     skip                      :: String -> String
 >     skip ""                   =  ""
@@ -510,7 +451,7 @@
 ks, 16.08.2004: At the end of the input, we might want to check for unbalanced if's or
 groups.
 
-> directive                     :: Lang -> Directive -> String 
+> directive                     :: Lang -> Directive -> String
 >                               -> (FilePath,LineNo) -> [CondInfo] -> Toggles
 >                               -> [Numbered Class] -> Formatter
 > directive lang d s (f,l) stack togs ts
@@ -523,11 +464,11 @@
 >   dir Else _ ((f,l,b2,b1):bs) =  skipOrFormat ((f, l, not b2 && b1, True) : bs) ts
 >   dir Endif _ ((f,l,b2,b1):bs)=  skipOrFormat bs ts
 >   dir EOF _ []                =  return ()  -- nothing left to do
->   dir EOF s bs                =  raise (init $ unlines (map unBalancedIf bs), s)
->   dir d s _                   =  raise ("spurious %" ++ decode d, s)
+>   dir EOF s bs                =  throwError (init $ unlines (map unBalancedIf bs), s)
+>   dir d s _                   =  throwError ("spurious %" ++ decode d, s)
 
 > skipOrFormat                  :: [CondInfo] -> [Numbered Class] -> Formatter
-> skipOrFormat stack ts         =  do  update (\st -> st{conds = stack})
+> skipOrFormat stack ts         =  do  modify (\st -> st{conds = stack})
 >                                      if andS stack  then formats ts
 >                                                     else skip ts
 
@@ -556,16 +497,13 @@
 computations, which should dramatically improve compilation time for
 documents that make extensive use of @\eval@ and @\perform@.
 
-> type Externals    =  FM.FiniteMap Char ProcessInfo
-> type ProcessInfo  =  (Handle, Handle, Handle, ProcessHandle)
-
 The function |external| can be used to call the process. It is discouraged
 to call any programs except @ghci@ or @hugs@, because we make a number of
 assumptions about the program being called. Input is the expression to evaluate.
 Output is the result in string form.
 
 > external                      :: String -> XIO Exc State String
-> external expr                 =  do st <- fetch
+> external expr                 =  do st <- get
 >                                     let os  =  opts st
 >                                         f   =  file st
 >                                         ex  =  externals st
@@ -579,13 +517,13 @@
 >                                     pi <- case FM.lookup f ex of
 >                                             Just pi  ->  return pi
 >                                             Nothing  ->  -- start new external process
->                                                          fromIO $ do
+>                                                          liftIO $ do
 >                                                            when (verbose st) $
 >                                                              hPutStrLn stderr $ "Starting external process: " ++ cmd
 >                                                            runInteractiveCommand cmd
->                                     store (st {externals = FM.add (f,pi) ex})
+>                                     put (st {externals = FM.add (f,pi) ex})
 >                                     let (pin,pout,_,_) = pi
->                                     fromIO $ do
+>                                     liftIO $ do
 >                                       -- hPutStrLn stderr ("sending: " ++ script)
 >                                       hPutStr pin script
 >                                       hFlush pin
@@ -595,10 +533,10 @@
 @:q@ command to them.
 
 > stopexternals                 :: Formatter
-> stopexternals                 =  do st <- fetch
+> stopexternals                 =  do st <- get
 >                                     let ex   =  externals st
 >                                         pis  =  map (ex FM.!) (FM.keys ex)
->                                     when (not . null $ pis) $ fromIO $ do
+>                                     when (not . null $ pis) $ liftIO $ do
 >                                       when (verbose st) $
 >                                         hPutStrLn stderr $ "Stopping external processes."
 >                                       mapM_ (\(pin,_,_,pid) -> do  hPutStrLn pin ":q"
@@ -643,370 +581,9 @@
 \subsubsection{Reading files}
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
-> dir, nondir                   :: FilePath -> FilePath
+> dir                           :: FilePath -> FilePath
 > dir filePath
 >     | null d                  =  ""
 >     | otherwise               =  reverse d
 >     where d                   =  dropWhile (/= '/') (reverse filePath)
->
-> nondir                        =  reverse . takeWhile (/= '/') . reverse
 
-% - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
-\subsubsection{GPL-related program information}
-% - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
-
-> programInfo                   :: String
-> programInfo                   =
->     "lhs2TeX " ++ version ++ ", Copyright (C) 1997-2011 Ralf Hinze, Andres Loeh\n\n\
->     \lhs2TeX comes with ABSOLUTELY NO WARRANTY;\n\
->     \for details type `lhs2TeX --warranty'.\n\
->     \This is free software, and you are welcome to redistribute it\n\
->     \under certain conditions; type `lhs2TeX --copying' for details."
-
-> copying                       :: String
-> copying                       =
->     "\t\t    GNU GENERAL PUBLIC LICENSE\n\
->     \\t\t       Version 2, June 1991\n\
->     \\n\
->     \ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
->     \                          59 Temple Place - Suite 330\n\
->     \                          Boston, MA 02111-1307, USA.\n\
->     \ Everyone is permitted to copy and distribute verbatim copies\n\
->     \ of this license document, but changing it is not allowed.\n\
->     \\n\
->     \\t\t\t    Preamble\n\
->     \\n\
->     \  The licenses for most software are designed to take away your\n\
->     \freedom to share and change it.  By contrast, the GNU General Public\n\
->     \License is intended to guarantee your freedom to share and change free\n\
->     \software--to make sure the software is free for all its users.  This\n\
->     \General Public License applies to most of the Free Software\n\
->     \Foundation's software and to any other program whose authors commit to\n\
->     \using it.  (Some other Free Software Foundation software is covered by\n\
->     \the GNU Library General Public License instead.)  You can apply it to\n\
->     \your programs, too.\n\
->     \\n\
->     \  When we speak of free software, we are referring to freedom, not\n\
->     \price.  Our General Public Licenses are designed to make sure that you\n\
->     \have the freedom to distribute copies of free software (and charge for\n\
->     \this service if you wish), that you receive source code or can get it\n\
->     \if you want it, that you can change the software or use pieces of it\n\
->     \in new free programs; and that you know you can do these things.\n\
->     \\n\
->     \  To protect your rights, we need to make restrictions that forbid\n\
->     \anyone to deny you these rights or to ask you to surrender the rights.\n\
->     \These restrictions translate to certain responsibilities for you if you\n\
->     \distribute copies of the software, or if you modify it.\n\
->     \\n\
->     \  For example, if you distribute copies of such a program, whether\n\
->     \gratis or for a fee, you must give the recipients all the rights that\n\
->     \you have.  You must make sure that they, too, receive or can get the\n\
->     \source code.  And you must show them these terms so they know their\n\
->     \rights.\n\
->     \\n\
->     \  We protect your rights with two steps: (1) copyright the software, and\n\
->     \(2) offer you this license which gives you legal permission to copy,\n\
->     \distribute and/or modify the software.\n\
->     \\n\
->     \  Also, for each author's protection and ours, we want to make certain\n\
->     \that everyone understands that there is no warranty for this free\n\
->     \software.  If the software is modified by someone else and passed on, we\n\
->     \want its recipients to know that what they have is not the original, so\n\
->     \that any problems introduced by others will not reflect on the original\n\
->     \authors' reputations.\n\
->     \\n\
->     \  Finally, any free program is threatened constantly by software\n\
->     \patents.  We wish to avoid the danger that redistributors of a free\n\
->     \program will individually obtain patent licenses, in effect making the\n\
->     \program proprietary.  To prevent this, we have made it clear that any\n\
->     \patent must be licensed for everyone's free use or not licensed at all.\n\
->     \\n\
->     \  The precise terms and conditions for copying, distribution and\n\
->     \modification follow.\n\
->     \\f\n\
->     \\t\t    GNU GENERAL PUBLIC LICENSE\n\
->     \   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
->     \\n\
->     \  0. This License applies to any program or other work which contains\n\
->     \a notice placed by the copyright holder saying it may be distributed\n\
->     \under the terms of this General Public License.  The \"Program\", below,\n\
->     \refers to any such program or work, and a \"work based on the Program\"\n\
->     \means either the Program or any derivative work under copyright law:\n\
->     \that is to say, a work containing the Program or a portion of it,\n\
->     \either verbatim or with modifications and/or translated into another\n\
->     \language.  (Hereinafter, translation is included without limitation in\n\
->     \the term \"modification\".)  Each licensee is addressed as \"you\".\n\
->     \\n\
->     \Activities other than copying, distribution and modification are not\n\
->     \covered by this License; they are outside its scope.  The act of\n\
->     \running the Program is not restricted, and the output from the Program\n\
->     \is covered only if its contents constitute a work based on the\n\
->     \Program (independent of having been made by running the Program).\n\
->     \Whether that is true depends on what the Program does.\n\
->     \\n\
->     \  1. You may copy and distribute verbatim copies of the Program's\n\
->     \source code as you receive it, in any medium, provided that you\n\
->     \conspicuously and appropriately publish on each copy an appropriate\n\
->     \copyright notice and disclaimer of warranty; keep intact all the\n\
->     \notices that refer to this License and to the absence of any warranty;\n\
->     \and give any other recipients of the Program a copy of this License\n\
->     \along with the Program.\n\
->     \\n\
->     \You may charge a fee for the physical act of transferring a copy, and\n\
->     \you may at your option offer warranty protection in exchange for a fee.\n\
->     \\n\
->     \  2. You may modify your copy or copies of the Program or any portion\n\
->     \of it, thus forming a work based on the Program, and copy and\n\
->     \distribute such modifications or work under the terms of Section 1\n\
->     \above, provided that you also meet all of these conditions:\n\
->     \\n\
->     \    a) You must cause the modified files to carry prominent notices\n\
->     \    stating that you changed the files and the date of any change.\n\
->     \\n\
->     \    b) You must cause any work that you distribute or publish, that in\n\
->     \    whole or in part contains or is derived from the Program or any\n\
->     \    part thereof, to be licensed as a whole at no charge to all third\n\
->     \    parties under the terms of this License.\n\
->     \\n\
->     \    c) If the modified program normally reads commands interactively\n\
->     \    when run, you must cause it, when started running for such\n\
->     \    interactive use in the most ordinary way, to print or display an\n\
->     \    announcement including an appropriate copyright notice and a\n\
->     \    notice that there is no warranty (or else, saying that you provide\n\
->     \    a warranty) and that users may redistribute the program under\n\
->     \    these conditions, and telling the user how to view a copy of this\n\
->     \    License.  (Exception: if the Program itself is interactive but\n\
->     \    does not normally print such an announcement, your work based on\n\
->     \    the Program is not required to print an announcement.)\n\
->     \\f\n\
->     \These requirements apply to the modified work as a whole.  If\n\
->     \identifiable sections of that work are not derived from the Program,\n\
->     \and can be reasonably considered independent and separate works in\n\
->     \themselves, then this License, and its terms, do not apply to those\n\
->     \sections when you distribute them as separate works.  But when you\n\
->     \distribute the same sections as part of a whole which is a work based\n\
->     \on the Program, the distribution of the whole must be on the terms of\n\
->     \this License, whose permissions for other licensees extend to the\n\
->     \entire whole, and thus to each and every part regardless of who wrote it.\n\
->     \\n\
->     \Thus, it is not the intent of this section to claim rights or contest\n\
->     \your rights to work written entirely by you; rather, the intent is to\n\
->     \exercise the right to control the distribution of derivative or\n\
->     \collective works based on the Program.\n\
->     \\n\
->     \In addition, mere aggregation of another work not based on the Program\n\
->     \with the Program (or with a work based on the Program) on a volume of\n\
->     \a storage or distribution medium does not bring the other work under\n\
->     \the scope of this License.\n\
->     \\n\
->     \  3. You may copy and distribute the Program (or a work based on it,\n\
->     \under Section 2) in object code or executable form under the terms of\n\
->     \Sections 1 and 2 above provided that you also do one of the following:\n\
->     \\n\
->     \    a) Accompany it with the complete corresponding machine-readable\n\
->     \    source code, which must be distributed under the terms of Sections\n\
->     \    1 and 2 above on a medium customarily used for software interchange; or,\n\
->     \\n\
->     \    b) Accompany it with a written offer, valid for at least three\n\
->     \    years, to give any third party, for a charge no more than your\n\
->     \    cost of physically performing source distribution, a complete\n\
->     \    machine-readable copy of the corresponding source code, to be\n\
->     \    distributed under the terms of Sections 1 and 2 above on a medium\n\
->     \    customarily used for software interchange; or,\n\
->     \\n\
->     \    c) Accompany it with the information you received as to the offer\n\
->     \    to distribute corresponding source code.  (This alternative is\n\
->     \    allowed only for noncommercial distribution and only if you\n\
->     \    received the program in object code or executable form with such\n\
->     \    an offer, in accord with Subsection b above.)\n\
->     \\n\
->     \The source code for a work means the preferred form of the work for\n\
->     \making modifications to it.  For an executable work, complete source\n\
->     \code means all the source code for all modules it contains, plus any\n\
->     \associated interface definition files, plus the scripts used to\n\
->     \control compilation and installation of the executable.  However, as a\n\
->     \special exception, the source code distributed need not include\n\
->     \anything that is normally distributed (in either source or binary\n\
->     \form) with the major components (compiler, kernel, and so on) of the\n\
->     \operating system on which the executable runs, unless that component\n\
->     \itself accompanies the executable.\n\
->     \\n\
->     \If distribution of executable or object code is made by offering\n\
->     \access to copy from a designated place, then offering equivalent\n\
->     \access to copy the source code from the same place counts as\n\
->     \distribution of the source code, even though third parties are not\n\
->     \compelled to copy the source along with the object code.\n\
->     \\f\n\
->     \  4. You may not copy, modify, sublicense, or distribute the Program\n\
->     \except as expressly provided under this License.  Any attempt\n\
->     \otherwise to copy, modify, sublicense or distribute the Program is\n\
->     \void, and will automatically terminate your rights under this License.\n\
->     \However, parties who have received copies, or rights, from you under\n\
->     \this License will not have their licenses terminated so long as such\n\
->     \parties remain in full compliance.\n\
->     \\n\
->     \  5. You are not required to accept this License, since you have not\n\
->     \signed it.  However, nothing else grants you permission to modify or\n\
->     \distribute the Program or its derivative works.  These actions are\n\
->     \prohibited by law if you do not accept this License.  Therefore, by\n\
->     \modifying or distributing the Program (or any work based on the\n\
->     \Program), you indicate your acceptance of this License to do so, and\n\
->     \all its terms and conditions for copying, distributing or modifying\n\
->     \the Program or works based on it.\n\
->     \\n\
->     \  6. Each time you redistribute the Program (or any work based on the\n\
->     \Program), the recipient automatically receives a license from the\n\
->     \original licensor to copy, distribute or modify the Program subject to\n\
->     \these terms and conditions.  You may not impose any further\n\
->     \restrictions on the recipients' exercise of the rights granted herein.\n\
->     \You are not responsible for enforcing compliance by third parties to\n\
->     \this License.\n\
->     \\n\
->     \  7. If, as a consequence of a court judgment or allegation of patent\n\
->     \infringement or for any other reason (not limited to patent issues),\n\
->     \conditions are imposed on you (whether by court order, agreement or\n\
->     \otherwise) that contradict the conditions of this License, they do not\n\
->     \excuse you from the conditions of this License.  If you cannot\n\
->     \distribute so as to satisfy simultaneously your obligations under this\n\
->     \License and any other pertinent obligations, then as a consequence you\n\
->     \may not distribute the Program at all.  For example, if a patent\n\
->     \license would not permit royalty-free redistribution of the Program by\n\
->     \all those who receive copies directly or indirectly through you, then\n\
->     \the only way you could satisfy both it and this License would be to\n\
->     \refrain entirely from distribution of the Program.\n\
->     \\n\
->     \If any portion of this section is held invalid or unenforceable under\n\
->     \any particular circumstance, the balance of the section is intended to\n\
->     \apply and the section as a whole is intended to apply in other\n\
->     \circumstances.\n\
->     \\n\
->     \It is not the purpose of this section to induce you to infringe any\n\
->     \patents or other property right claims or to contest validity of any\n\
->     \such claims; this section has the sole purpose of protecting the\n\
->     \integrity of the free software distribution system, which is\n\
->     \implemented by public license practices.  Many people have made\n\
->     \generous contributions to the wide range of software distributed\n\
->     \through that system in reliance on consistent application of that\n\
->     \system; it is up to the author/donor to decide if he or she is willing\n\
->     \to distribute software through any other system and a licensee cannot\n\
->     \impose that choice.\n\
->     \\n\
->     \This section is intended to make thoroughly clear what is believed to\n\
->     \be a consequence of the rest of this License.\n\
->     \\f\n\
->     \  8. If the distribution and/or use of the Program is restricted in\n\
->     \certain countries either by patents or by copyrighted interfaces, the\n\
->     \original copyright holder who places the Program under this License\n\
->     \may add an explicit geographical distribution limitation excluding\n\
->     \those countries, so that distribution is permitted only in or among\n\
->     \countries not thus excluded.  In such case, this License incorporates\n\
->     \the limitation as if written in the body of this License.\n\
->     \\n\
->     \  9. The Free Software Foundation may publish revised and/or new versions\n\
->     \of the General Public License from time to time.  Such new versions will\n\
->     \be similar in spirit to the present version, but may differ in detail to\n\
->     \address new problems or concerns.\n\
->     \\n\
->     \Each version is given a distinguishing version number.  If the Program\n\
->     \specifies a version number of this License which applies to it and \"any\n\
->     \later version\", you have the option of following the terms and conditions\n\
->     \either of that version or of any later version published by the Free\n\
->     \Software Foundation.  If the Program does not specify a version number of\n\
->     \this License, you may choose any version ever published by the Free Software\n\
->     \Foundation.\n\
->     \\n\
->     \  10. If you wish to incorporate parts of the Program into other free\n\
->     \programs whose distribution conditions are different, write to the author\n\
->     \to ask for permission.  For software which is copyrighted by the Free\n\
->     \Software Foundation, write to the Free Software Foundation; we sometimes\n\
->     \make exceptions for this.  Our decision will be guided by the two goals\n\
->     \of preserving the free status of all derivatives of our free software and\n\
->     \of promoting the sharing and reuse of software generally.\n\
->     \\n"
->     ++ warranty ++
->     "\n\n\
->     \\t\t     END OF TERMS AND CONDITIONS\n\
->     \\f\n\
->     \\t    How to Apply These Terms to Your New Programs\n\
->     \\n\
->     \  If you develop a new program, and you want it to be of the greatest\n\
->     \possible use to the public, the best way to achieve this is to make it\n\
->     \free software which everyone can redistribute and change under these terms.\n\
->     \\n\
->     \  To do so, attach the following notices to the program.  It is safest\n\
->     \to attach them to the start of each source file to most effectively\n\
->     \convey the exclusion of warranty; and each file should have at least\n\
->     \the \"copyright\" line and a pointer to where the full notice is found.\n\
->     \\n\
->     \    <one line to give the program's name and a brief idea of what it does.>\n\
->     \    Copyright (C) 19yy  <name of author>\n\
->     \\n\
->     \    This program is free software; you can redistribute it and/or modify\n\
->     \    it under the terms of the GNU General Public License as published by\n\
->     \    the Free Software Foundation; either version 2 of the License, or\n\
->     \    (at your option) any later version.\n\
->     \\n\
->     \    This program is distributed in the hope that it will be useful,\n\
->     \    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
->     \    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
->     \    GNU General Public License for more details.\n\
->     \\n\
->     \    You should have received a copy of the GNU General Public License\n\
->     \    along with this program; see the file COPYING.  If not, write to\n\
->     \    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n\
->     \    Boston, MA 02111-1307, USA.\n\
->     \\n\
->     \Also add information on how to contact you by electronic and paper mail.\n\
->     \\n\
->     \If the program is interactive, make it output a short notice like this\n\
->     \when it starts in an interactive mode:\n\
->     \\n\
->     \    Gnomovision version 69, Copyright (C) 19yy name of author\n\
->     \    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n\
->     \    This is free software, and you are welcome to redistribute it\n\
->     \    under certain conditions; type `show c' for details.\n\
->     \\n\
->     \The hypothetical commands `show w' and `show c' should show the appropriate\n\
->     \parts of the General Public License.  Of course, the commands you use may\n\
->     \be called something other than `show w' and `show c'; they could even be\n\
->     \mouse-clicks or menu items--whatever suits your program.\n\
->     \\n\
->     \You should also get your employer (if you work as a programmer) or your\n\
->     \school, if any, to sign a \"copyright disclaimer\" for the program, if\n\
->     \necessary.  Here is a sample; alter the names:\n\
->     \\n\
->     \  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n\
->     \  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\
->     \\n\
->     \  <signature of Ty Coon>, 1 April 1989\n\
->     \  Ty Coon, President of Vice\n\
->     \\n\
->     \This General Public License does not permit incorporating your program into\n\
->     \proprietary programs.  If your program is a subroutine library, you may\n\
->     \consider it more useful to permit linking proprietary applications with the\n\
->     \library.  If this is what you want to do, use the GNU Library General\n\
->     \Public License instead of this License."
-
-> warranty                      :: String
-> warranty                      =
->     "\t\t\t    NO WARRANTY\n\
->     \\n\
->     \  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
->     \FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n\
->     \OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
->     \PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
->     \OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
->     \MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n\
->     \TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n\
->     \PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
->     \REPAIR OR CORRECTION.\n\
->     \\n\
->     \  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
->     \WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
->     \REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
->     \INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
->     \OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
->     \TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
->     \YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
->     \PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
->     \POSSIBILITY OF SUCH DAMAGES."
diff --git a/src/Math.lhs b/src/Math.lhs
--- a/src/Math.lhs
+++ b/src/Math.lhs
@@ -10,7 +10,9 @@
 > import Prelude hiding         (  lines )
 > import Data.List              (  partition )
 > import Numeric                (  showFFloat )
-> import Control.Monad          (  MonadPlus(..) )
+> import Control.Applicative    (  many )
+> import Control.Arrow          (  (>>>) )
+> import Control.Monad          (  MonadPlus(..), (>=>) )
 >
 > import Verbatim               (  expand, trim )
 > import Typewriter             (  latex )
@@ -30,35 +32,35 @@
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
 > inline                        :: Lang -> Formats -> Bool -> String -> Either Exc Doc
-> inline lang fmts auto         =  fmap unNL
->                               .> tokenize lang
->                               @> lift (number 1 1)
->                               @> when auto (lift (filter (isNotSpace . token)))
->                               @> lift (partition (\t -> catCode t /= White))
->                               @> exprParse *** return
->                               @> lift (substitute fmts auto) *** return
->                               @> lift (uncurry merge)
->                               @> lift (fmap token)
->                               @> when auto (lift addSpaces)
->                               @> lift (latexs fmts)
->                               @> lift sub'inline
+> inline lang fmts auto         =   fmap unNL
+>                               >>> tokenize lang
+>                               >=> lift (number 1 1)
+>                               >=> when auto (lift (filter (isNotSpace . token)))
+>                               >=> lift (partition (\t -> catCode t /= White))
+>                               >=> exprParse *** return
+>                               >=> lift (substitute fmts auto) *** return
+>                               >=> lift (uncurry merge)
+>                               >=> lift (fmap token)
+>                               >=> when auto (lift addSpaces)
+>                               >=> lift (latexs fmts)
+>                               >=> lift sub'inline
 
 > display                       :: Lang -> Formats -> Bool -> (Stack, Stack) -> Maybe Int
 >                               -> String -> Either Exc (Doc, (Stack,Stack))
-> display lang fmts auto sts col=  lift trim
->                               @> lift (expand 0)
->                               @> tokenize lang
->                               @> lift (number 1 1)
->                               @> when auto (lift (filter (isNotSpace . token)))
->                               @> lift (partition (\t -> catCode t /= White))
->                               @> exprParse *** return
->                               @> lift (substitute fmts auto) *** return
->                               @> lift (uncurry merge)
->                               @> lift lines
->                               @> lift (align col)
->                               @> when auto (lift (fmap (fmap addSpaces)))
->                               @> lift (leftIndent fmts auto sts)
->                               @> lift sub'code *** return
+> display lang fmts auto sts col=   lift trim
+>                               >=> lift (expand 0)
+>                               >=> tokenize lang
+>                               >=> lift (number 1 1)
+>                               >=> when auto (lift (filter (isNotSpace . token)))
+>                               >=> lift (partition (\t -> catCode t /= White))
+>                               >=> exprParse *** return
+>                               >=> lift (substitute fmts auto) *** return
+>                               >=> lift (uncurry merge)
+>                               >=> lift lines
+>                               >=> lift (align col)
+>                               >=> when auto (lift (fmap (fmap addSpaces)))
+>                               >=> lift (leftIndent fmts auto sts)
+>                               >=> lift sub'code *** return
 
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 \subsubsection{A very simple Haskell Parser}
diff --git a/src/MathCommon.lhs b/src/MathCommon.lhs
--- a/src/MathCommon.lhs
+++ b/src/MathCommon.lhs
@@ -18,6 +18,7 @@
 >
 > import Control.Monad
 
+> when :: Monad m => Bool -> (a -> m a) -> (a -> m a)
 > when True f                   =  f
 > when False f                  =  return
 
diff --git a/src/MathPoly.lhs b/src/MathPoly.lhs
--- a/src/MathPoly.lhs
+++ b/src/MathPoly.lhs
@@ -16,7 +16,9 @@
 > import Prelude hiding         (  lines )
 > import Data.List              (  partition, nub, insert, sort, transpose )
 > import Numeric                (  showFFloat )
-> import Control.Monad          (  MonadPlus(..) )
+> import Control.Applicative    (  many )
+> import Control.Arrow          (  (>>>) )
+> import Control.Monad          (  MonadPlus(..), (>=>) )
 >
 > import Verbatim               (  expand, trim )
 > import Typewriter             (  latex )
@@ -37,47 +39,47 @@
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
 > inline                        :: Lang -> Formats -> Bool -> String -> Either Exc Doc
-> inline lang fmts auto         =  fmap unNL
->                               .> tokenize lang
->                               @> lift (number 1 1)
->                               @> when auto (lift (filter (isNotSpace . token)))
->                               @> lift (partition (\t -> catCode t /= White))
->                               @> exprParse *** return
->                               @> lift (substitute fmts auto) *** return
->                               @> lift (uncurry merge)
->                               @> lift (fmap token)
->                               @> when auto (lift addSpaces)
->                               @> lift (latexs fmts)
->                               @> lift sub'inline
+> inline lang fmts auto         =   fmap unNL
+>                               >>> tokenize lang
+>                               >=> lift (number 1 1)
+>                               >=> when auto (lift (filter (isNotSpace . token)))
+>                               >=> lift (partition (\t -> catCode t /= White))
+>                               >=> exprParse *** return
+>                               >=> lift (substitute fmts auto) *** return
+>                               >=> lift (uncurry merge)
+>                               >=> lift (fmap token)
+>                               >=> when auto (lift addSpaces)
+>                               >=> lift (latexs fmts)
+>                               >=> lift sub'inline
 
 > display                       :: Lang -> Int -> Formats -> Bool -> Int -> Int -> Stack
 >                               -> String -> Either Exc (Doc, Stack)
 > display lang line fmts auto sep lat stack
->                               =  lift trim
->                               @> lift (expand 0)
->                               @> tokenize lang
->                               @> lift (number line 1)
->       --                     |@> when auto (lift (filter (isNotSpace . token)))|
->                               @> lift (partition (\t -> catCode t /= White))
->                               @> exprParse *** return
->                               @> lift (substitute fmts auto) *** return
->                               @> lift (uncurry merge)
->                               @> lift lines
->                               @> when auto (lift (fmap addSpaces))
->                               @> lift (\ts -> (autoalign sep ts,ts))
->       --                     |@> lift (\(x,y) -> trace ((unlines $ map show $ y) ++ "\n" ++ show x) (x,y))|
->                               @> lift (\(cs,ts) -> let ats = align cs sep lat ts
->                                                        cs' = [("B",0)] ++ cs 
->                                                           ++ [("E",error "E column")]
->                                                    in  (autocols cs' ats,ats)
->                                       )
->                               @> return *** when auto (lift (fmap (fmap (filter (isNotSpace . token)))))
->       --                     |@> return *** when auto (lift (fmap (fmap (addSpaces . filter (isNotSpace . token)))))|
->                               @> lift (\((cs,z),ats) -> (cs,(z,ats)))
->                               @> return *** lift (\(z,ats) -> leftIndent fmts auto z [] ats)
+>                               =   lift trim
+>                               >=> lift (expand 0)
+>                               >=> tokenize lang
+>                               >=> lift (number line 1)
+>       --                     |>=> when auto (lift (filter (isNotSpace . token)))|
+>                               >=> lift (partition (\t -> catCode t /= White))
+>                               >=> exprParse *** return
+>                               >=> lift (substitute fmts auto) *** return
+>                               >=> lift (uncurry merge)
+>                               >=> lift lines
+>                               >=> when auto (lift (fmap addSpaces))
+>                               >=> lift (\ts -> (autoalign sep ts,ts))
+>       --                     |>=> lift (\(x,y) -> trace ((unlines $ map show $ y) ++ "\n" ++ show x) (x,y))|
+>                               >=> lift (\(cs,ts) -> let ats = align cs sep lat ts
+>                                                         cs' = [("B",0)] ++ cs 
+>                                                            ++ [("E",error "E column")]
+>                                                     in  (autocols cs' ats,ats)
+>                                        )
+>                               >=> return *** when auto (lift (fmap (fmap (filter (isNotSpace . token)))))
+>       --                     |>=> return *** when auto (lift (fmap (fmap (addSpaces . filter (isNotSpace . token)))))|
+>                               >=> lift (\((cs,z),ats) -> (cs,(z,ats)))
+>                               >=> return *** lift (\(z,ats) -> leftIndent fmts auto z [] ats)
 >       -- ks, 17.07.2003: i've changed "stack" into "[]" and thereby disabled
 >       -- the global stack for now as it leads to unexepected behaviour
->                               @> lift (\(cs,(d,stack)) -> (sub'code (columns cs <> d),stack))
+>                               >=> lift (\(cs,(d,stack)) -> (sub'code (columns cs <> d),stack))
 >
 > columns                       :: [(String,Doc)] -> Doc
 > columns                       =  foldr (<>) Empty 
diff --git a/src/NewCode.lhs b/src/NewCode.lhs
--- a/src/NewCode.lhs
+++ b/src/NewCode.lhs
@@ -13,6 +13,7 @@
 > module NewCode                (  module NewCode  )
 > where
 >
+> import Control.Monad          (  (>=>) )
 > import Data.List              (  partition )
 >
 > import Verbatim               (  trim, expand )
@@ -34,17 +35,17 @@
 in the ``real'' program code. All comments are deleted.
 
 > display                       :: Lang -> Formats -> String -> Either Exc Doc
-> display lang fmts             =  lift trim
->                               @> lift (expand 0)
->                               @> tokenize lang
->                               @> lift (number 1 1)
->                               @> lift (partition (\t -> catCode t /= White))
->                               @> exprParse *** return
->                               @> lift (substitute fmts False) *** return
->                               @> lift (uncurry merge)
->                               @> lift (fmap token)
->                               @> lift (latexs sub'space sub'nl fmts)
->                               @> lift sub'code
+> display lang fmts             =   lift trim
+>                               >=> lift (expand 0)
+>                               >=> tokenize lang
+>                               >=> lift (number 1 1)
+>                               >=> lift (partition (\t -> catCode t /= White))
+>                               >=> exprParse *** return
+>                               >=> lift (substitute fmts False) *** return
+>                               >=> lift (uncurry merge)
+>                               >=> lift (fmap token)
+>                               >=> lift (latexs sub'space sub'nl fmts)
+>                               >=> lift sub'code
 
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 \subsubsection{Encoding}
diff --git a/src/Parser.lhs b/src/Parser.lhs
--- a/src/Parser.lhs
+++ b/src/Parser.lhs
@@ -9,7 +9,8 @@
 >
 > import Data.Char              (  isSpace  )
 > import Auxiliaries
-> import Control.Monad          (  MonadPlus(..), filterM  )
+> import Control.Applicative
+> import Control.Monad          (  MonadPlus(..), filterM, ap  )
 
 %endif
 Deterministische Mini-Parser.
@@ -37,6 +38,12 @@
 > instance MonadPlus  (Parser tok) where
 >     mzero                     =  MkParser (\inp -> Nothing)
 >     m `mplus` n               =  MkParser (\inp -> unParser m inp `mplus` unParser n inp)
+> instance Applicative (Parser tok) where
+>     pure                      =  return
+>     (<*>)                     =  ap
+> instance Alternative (Parser tok) where
+>     empty                     =  mzero
+>     (<|>)                     =  mplus
 >
 > satisfy                       :: (tok -> Bool) -> Parser tok tok
 > satisfy pred                  =  MkParser (\inp -> case inp of
diff --git a/src/State.lhs b/src/State.lhs
new file mode 100644
--- /dev/null
+++ b/src/State.lhs
@@ -0,0 +1,81 @@
+
+> module State
+> where
+>
+> import System.IO
+> import System.Process
+>
+> import Version
+> import TeXCommands
+> import qualified Math
+> import qualified MathPoly as Poly
+> import Directives
+> import qualified FiniteMap as FM
+> import Auxiliaries
+
+> type CondInfo                 =  (FilePath, LineNo, Bool, Bool)
+>
+> data State                    =  State { style      :: Style,
+>                                          lang       :: Lang,          -- Haskell or Agda, currently
+>                                          verbose    :: Bool,
+>                                          searchpath :: [FilePath],
+>                                          file       :: FilePath,      -- also used for `hugs'
+>                                          lineno     :: LineNo,
+>                                          ofile      :: FilePath,
+>                                          olineno    :: LineNo,
+>                                          atnewline  :: Bool,
+>                                          fldir      :: Bool,          -- file/linenumber directives
+>                                          pragmas    :: Bool,          -- generate LINE pragmas?
+>                                          output     :: Handle,
+>                                          opts       :: String,        -- options for `hugs'
+>                                          files      :: [(FilePath, LineNo)], -- includees (?)
+>                                          path       :: FilePath,      -- for relative includes
+>                                          fmts       :: Formats,
+>                                          subst      :: Substs,
+>                                          stack      :: [Formats],     -- for grouping
+>                                          toggles    :: Toggles,       -- @%let@ defined toggles
+>                                          conds      :: [CondInfo],    -- for conditional directives
+>                                          align      :: Maybe Int,     -- math: internal alignment column
+>                                          stacks     :: (Math.Stack, Math.Stack),      -- math: indentation stacks
+>                                          separation :: Int,           -- poly: separation
+>                                          latency    :: Int,           -- poly: latency
+>                                          pstack     :: Poly.Stack,    -- poly: indentation stack
+>                                          externals  :: Externals      -- catchErrors for external processes (hugs,ghci)
+>                                        }
+>
+> type Externals    =  FM.FiniteMap Char ProcessInfo
+> type ProcessInfo  =  (Handle, Handle, Handle, ProcessHandle)
+
+Initial state.
+
+> state0                        :: State
+> state0                        =  State { lang       = Haskell,
+>                                          verbose    = False,
+>                                          searchpath = searchPath,
+>                                          lineno     = 0,
+>                                          olineno    = 0,
+>                                          atnewline  = True,
+>                                          fldir      = False,
+>                                          pragmas    = True,
+>                                          output     = stdout,
+>                                          opts       = "",
+>                                          files      = [],
+>                                          path       = "",
+>                                          fmts       = FM.empty,
+>                                          subst      = FM.empty,
+>                                          stack      = [],
+>                                          conds      = [],
+>                                          align      = Nothing,
+>                                          stacks     = ([], []),
+>                                          separation = 2,
+>                                          latency    = 2,
+>                                          pstack     = [],
+>                                          -- ks, 03.01.04: added to prevent warnings during compilation
+>                                          style      = error "uninitialized style",
+>                                          file       = error "uninitialized filename",
+>                                          ofile      = error "uninitialized filename",
+>                                          toggles    = error "uninitialized toggles",
+>                                          externals  = FM.empty
+>                                        }
+
+
diff --git a/src/StateT.lhs b/src/StateT.lhs
--- a/src/StateT.lhs
+++ b/src/StateT.lhs
@@ -4,22 +4,31 @@
 
 %if codeOnly || showModuleHeader
 
+> {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 > module StateT                 (  module StateT  )
 > where
 >
+> import Control.Applicative
+> import Control.Monad.Error
+> import Control.Monad.State
+>
 > import Auxiliaries
 
 %endif
 
-|IO| mit internem Zustand und Fehlerbehandlung.
+|IO| with internal state and error handling.
 
 %if style == math
 %format MkXIO (m) = m
 %format unXIO (m) = m
 %endif
 
-> newtype XIO exc st a          =  MkXIO (st -> IO (Either exc a, st))
+> newtype XIO exc st a          =  MkXIO (ErrorT exc (StateT st IO) a)
+>   deriving (Functor, Applicative, Monad, MonadIO, MonadState st, MonadError exc)
 
+-- XIO exc st a ~= StateT st IO (Either exc a)
+--              ~= ErrorT exc (StateT st IO) a
+
 %if style /= math
 
 > unXIO (MkXIO f)               =  f
@@ -28,43 +37,12 @@
 
 \NB The state is preserved upon failure.
 
-> instance Functor (XIO exc st) where
->     fmap f m                  =  m >>= \a -> return (f a)
->
-> instance Monad (XIO exc st) where
->     return a                  =  MkXIO (\st -> return (Right a, st))
->     m >>= k                   =  MkXIO (\st -> do (r, st') <- unXIO m st
->                                                   case r of
->                                                     Left e  -> return (Left e, st')
->                                                     Right a -> unXIO (k a) st')
-
-\NB We cannot replace |return (Left e, st')| by |return (r, st')| since
-the type is not general enough then.
+> toIO                          :: Error exc => XIO exc st a -> IO a
+> toIO (MkXIO m)                =  do
+>                                    (r, _) <- runStateT (runErrorT m)
+>                                                        (error "no initial state supplied")
+>                                    case r of Left  _ -> error "unhandled error"
+>                                              Right x -> return x
 
-> fetch                         :: XIO exc st st
-> fetch                         =  MkXIO (\st -> return (Right st, st))
->
-> store                         :: st -> XIO exc st ()
-> store st'                     =  MkXIO (\st -> return (Right (), st'))
->
-> update                        :: (st -> st) -> XIO exc st ()
-> update f                      =  do st <- fetch; store (f st)
->
-> toIO                          :: XIO exc st a -> IO a
-> toIO m                        =  do (a, _) <- unXIO m undefined; return (fromRight a)
->
-> fromIO                        :: IO a -> XIO exc st a
-> fromIO m                      =  MkXIO (\st -> do a <- m; return (Right a, st))
->
-> raise                         :: exc -> XIO exc st a
-> raise e                       =  MkXIO (\st -> return (Left e, st))
->
-> try                           :: XIO exc st a -> XIO exc' st (Either exc a)
-> try m                         =  MkXIO (\st -> do (r, st') <- unXIO m st; return (Right r, st'))
->
->
-> handle                        :: XIO exc st a -> (exc -> XIO exc' st a) -> XIO exc' st a
-> handle m h                    =  try m >>= either h return
->
-> fromEither                    :: Either exc a -> XIO exc st a
-> fromEither                    =  either raise return
+> fromEither                    :: Error exc => Either exc a -> XIO exc st a
+> fromEither                    =  either throwError return
diff --git a/src/Typewriter.lhs b/src/Typewriter.lhs
--- a/src/Typewriter.lhs
+++ b/src/Typewriter.lhs
@@ -7,6 +7,8 @@
 > module Typewriter             (  module Typewriter  )
 > where
 >
+> import Control.Monad
+>
 > import Verbatim ( trim, expand )
 > import Document
 > import Directives
@@ -22,15 +24,15 @@
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 
 > inline, display               :: Lang -> Formats -> String -> Either Exc Doc
-> inline lang dict              =  tokenize lang
->                               @> lift (latexs sub'thin sub'thin dict)
->                               @> lift sub'inline
+> inline lang dict              =   tokenize lang
+>                               >=> lift (latexs sub'thin sub'thin dict)
+>                               >=> lift sub'inline
 
-> display lang dict             =  lift trim
->                               @> lift (expand 0)
->                               @> tokenize lang
->                               @> lift (latexs sub'space sub'nl dict)
->                               @> lift sub'code
+> display lang dict             =   lift trim
+>                               >=> lift (expand 0)
+>                               >=> tokenize lang
+>                               >=> lift (latexs sub'space sub'nl dict)
+>                               >=> lift sub'code
 
 % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - -
 \subsubsection{\LaTeX\ encoding}
@@ -42,20 +44,20 @@
 > latex                         :: Doc -> Doc -> Formats -> Token -> Doc
 > latex sp nl dict              =  tex Empty
 >     where
->     tex _ (Space s)           =  sub'spaces (convert s)
->     tex q (Conid s)           =  replace q s (sub'conid (q <> convert s))
+>     tex _ (Space s)           =  sub'spaces (convert False s)
+>     tex q (Conid s)           =  replace q s (sub'conid (q <> convert False s))
 >     tex _ (Varid "")          =  sub'dummy    -- HACK
->     tex q (Varid s)           =  replace q s (sub'varid (q <> convert s))
->     tex q (Consym s)          =  replace q s (sub'consym (q <> convert s))
->     tex q (Varsym s)          =  replace q s (sub'varsym (q <> convert s))
->     tex _ (Numeral s)         =  replace Empty s (sub'numeral (convert s)) -- NEU
+>     tex q (Varid s)           =  replace q s (sub'varid (q <> convert False s))
+>     tex q (Consym s)          =  replace q s (sub'consym (q <> convert False s))
+>     tex q (Varsym s)          =  replace q s (sub'varsym (q <> convert False s))
+>     tex _ (Numeral s)         =  replace Empty s (sub'numeral (convert True s)) -- NEU
 >     tex _ (Char s)            =  sub'char (catenate (map conv' (init $ tail s))) -- NEW: remove quotes
 >     tex _ (String s)          =  sub'string (catenate (map conv' (init $ tail s))) -- NEW: remove quotes
->     tex _ (Special c)         =  sub'special (replace Empty [c] (conv c))
+>     tex _ (Special c)         =  sub'special (replace Empty [c] (conv False c))
 >     tex _ (Comment s)         =  sub'comment (Embedded s)
 >     tex _ (Nested s)          =  sub'nested (Embedded s)
 >     tex _ (Pragma s)          =  sub'pragma (Embedded s)
->     tex _ (Keyword s)         =  replace Empty s (sub'keyword (convert s))
+>     tex _ (Keyword s)         =  replace Empty s (sub'keyword (convert False s))
 >     tex _ (TeX False d)       =  d
 >     tex _ (TeX True d)        =  sub'tex d
 >     tex _ t@(Qual ms t')      =  replace Empty (string t) (tex (catenate (map (\m -> tex Empty (Conid m) <> Text ".") ms)) t')
@@ -71,20 +73,22 @@
  
 \NB Only nullary macros are applied.
 
-Conversion of strings and characters.
+Conversion of strings and characters. The Boolean indicates whether we
+want to convert a numeric literal which could contain an exponent.
 
->     convert                   :: String -> Doc
->     convert s                 =  catenate (map conv s)
->     conv                      :: Char -> Doc
->     conv ' '                  =  sp
->     conv '\n'                 =  nl
->     conv c
+>     convert                   :: Bool -> String -> Doc
+>     convert isNum s           =  catenate (map (conv isNum) s)
+>     conv                      :: Bool -> Char -> Doc
+>     conv _ ' '                =  sp
+>     conv _ '\n'               =  nl
+>     conv isNum c
 >       | c `elem` "#$%&"       =  Text ("\\" ++ [c])
 >       | c `elem` "\"\\^_{}~"  =  Text (char c)
+>       | isNum && c `elem` "-+"=  Text ("{" ++ [c] ++ "}")
 >       | otherwise             =  Text [c]
 >
 >     conv' ' '                 =  Text "~" -- NEW: instead of |Text (char ' ')| -- for character and string literals
->     conv' c                   =  conv c
+>     conv' c                   =  conv False c
 
 \NB The character @"@ is not copied verbatim, to be able to use
 @german.sty@ (@"@ is made active).
diff --git a/src/Verbatim.lhs b/src/Verbatim.lhs
--- a/src/Verbatim.lhs
+++ b/src/Verbatim.lhs
@@ -7,7 +7,9 @@
 > module Verbatim               (  module Verbatim  )
 > where
 >
+> import Control.Arrow          (  (>>>) )
 > import Data.Char
+> import Data.List              (  intersperse )
 >
 > import Document
 > import Auxiliaries
@@ -21,18 +23,18 @@
 The Boolean flag indicates whether a space should be typeset as \verb*| | (|True|) or not.
 
 > inline                        :: Bool -> String -> Doc
-> inline b                      =  latexs b .> sub'verb
+> inline b                      =  latexs b >>> sub'verb
 >
 > display                       :: Int -> Bool -> String -> Doc
-> display width b               =  trim
->                               .> expand 0
->                               .> lines
->                               .> map (group width)
->                               .> map (map (latexs b))
->                               .> map splice
->                               .> intersperse sub'verbnl
->                               .> catenate
->                               .> sub'verbatim
+> display width b               =   trim
+>                               >>> expand 0
+>                               >>> lines
+>                               >>> map (group width)
+>                               >>> map (map (latexs b))
+>                               >>> map splice
+>                               >>> intersperse sub'verbnl
+>                               >>> catenate
+>                               >>> sub'verbatim
 >
 > splice                        :: [Doc] -> Doc
 > splice ds                     =  Text "~" <> catenate (intersperse nl ds)
@@ -62,7 +64,7 @@
 Delete leading and trailing blank line(s).
 
 > trim                          :: String -> String
-> trim                          =  skip .> reverse .> skip .> reverse
+> trim                          =  skip >>> reverse >>> skip >>> reverse
 >
 > skip                          :: String -> String
 > skip ""                       =  ""
