--- haskell-hsh-2.0.3.orig/test.hs
+++ haskell-hsh-2.0.3/test.hs
@@ -0,0 +1,19 @@
+import HSH
+import Text.Printf
+import System.Log.Logger
+import System.Log.Handler.Syslog
+import Data.Char
+
+main =
+ do s <- openlog "test" [PID] USER DEBUG
+ updateGlobalLogger rootLoggerName (addHandler s . setLevel DEBUG)
+ --runIO $ "ls testsrc/testdata" -|- (map toUpper) -|- grep "BA"
+ str <- run $ echo "bar\nbaz\nfoo\nquux\n" -|- "tr a-z A-Z"
+ putStrLn str
+ --runIO $ echo "bar\nbaz\nfoo\nquux\n" -|- "tr a-z A-Z" -|- "grep BA"
+ --run $ ("ls", ["-l"]) -|- countLines -|- ("grep", ["hs$"])
+ --run $ (id::(String -> String)) -|- ("wc", ["-l"]) -|- countLines -|- ("grep", ["1"])
+ --run $ ("ls", ["-l"]) -|- ("wc", ["-l"])
+
+countLines :: [String] -> [String]
+countLines = zipWith (\i line -> printf "%-5d %s" i line) [(1::Int)..]
--- haskell-hsh-2.0.3.orig/Makefile
+++ haskell-hsh-2.0.3/Makefile
@@ -0,0 +1,48 @@
+# Copyright (C) 2004 - 2009 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+all: setup
+ @echo "Please use Cabal to build this package; not make."
+ ./setup configure
+ ./setup build
+
+setup: Setup.lhs
+ ghc --make -o setup Setup.lhs
+
+install: setup
+ ./setup install
+
+clean:
+ -./setup clean
+ -rm -f setup
+
+.PHONY: test
+test: test-ghc # test-hugs
+ @echo ""
+ @echo "All tests pass."
+
+test-hugs: setup
+ @echo " ****** Running hugs tests"
+ ./setup configure -f buildtests --hugs
+ ./setup build
+ runhugs -98 +o -P$(PWD)/dist/scratch:$(PWD)/dist/scratch/programs/runtests: \
+ dist/scratch/programs/runtests/Main.hs
+
+test-ghc: setup
+ @echo " ****** Building GHC tests"
+ ./setup configure -f buildtests
+ ./setup build
+ @echo " ****** Running GHC tests"
+ ./dist/build/runtests/runtests
--- haskell-hsh-2.0.3.orig/test2.hs
+++ haskell-hsh-2.0.3/test2.hs
@@ -0,0 +1,12 @@
+import HSH
+import HSH.ShellEquivs
+import System.Log.Logger
+
+main = do -- updateGlobalLogger rootLoggerName (setLevel DEBUG)
+ putStrLn " ******* RUN 1"
+ r <- runS ("ls -l" -|- "grep i" -|- wcL)
+ putStrLn $ " ******* RUN 1 result: " ++ show r
+ putStrLn " ******* RUN 2"
+ r2 <- runS ("ls -l" -|- grep "i" -|- wcL)
+ putStrLn $ " ******* RUN 2 result: " ++ show r2
+
--- haskell-hsh-2.0.3.orig/HSH.cabal
+++ haskell-hsh-2.0.3/HSH.cabal
@@ -23,6 +23,11 @@
description: Build the executable to run unit tests
default: False
+flag threaded
+ default: True
+ description: Build with support for multithreaded execution
+
+
library
Exposed-Modules: HSH, HSH.Command, HSH.ShellEquivs, HSH.Channel
Extensions: ExistentialQuantification, OverlappingInstances,
@@ -32,7 +37,9 @@
bytestring
if !os(windows)
Build-Depends: unix
- GHC-Options: -O2 -threaded -Wall
+ GHC-Options: -O2 -Wall
+ if flag(threaded)
+ GHC-Options: -threaded
Executable runtests
if flag(buildtests)
@@ -49,4 +56,6 @@
HS-Source-Dirs: testsrc, .
Extensions: ExistentialQuantification, OverlappingInstances,
UndecidableInstances, FlexibleContexts, CPP
- GHC-Options: -O2 -threaded
+ GHC-Options: -O2
+ if flag(threaded)
+ GHC-Options: -threaded
--- haskell-hsh-2.0.3.orig/testsrc/ShellEquivsTest.hs
+++ haskell-hsh-2.0.3/testsrc/ShellEquivsTest.hs
@@ -0,0 +1,117 @@
+{-
+Copyright (C) 2004-2007 John Goerzen <jgoerzen@complete.org>
+Please see the COPYRIGHT file
+-}
+
+module ShellEquivsTest(tests) where
+import Test.HUnit
+import Test.HUnit.Tools
+import HSH
+import HSH.ShellEquivs
+import TestUtils
+import Data.Char
+import Control.Exception
+import Data.List
+
+tabspath = [] -- FIXME: need some way to test this
+
+tbasenamedirname t =
+ [t "" "." ".",
+ t "/" "/" "/",
+ t "/foo" "foo" "/",
+ t "/foo/bar" "bar" "/foo",
+ t "/foo/" "foo" "/",
+ t "./" "." ".",
+ t "/foo/bar/" "bar" "/foo",
+ t "/foo/bar/." "." "/foo/bar",
+ t "/foo/bar/./" "." "/foo/bar",
+ t "foo" "foo" ".",
+ t "/usr/lib" "lib" "/usr",
+ t "/usr/" "usr" "/",
+ t "usr" "usr" ".",
+ t "." "." ".",
+ t ".." ".." "."
+ ]
+
+tbasename =
+ tbasenamedirname
+ (\inp expbn expdn -> TestLabel inp $ TestCase $ assertEqual inp expbn (basename inp))
+
+tdirname =
+ tbasenamedirname
+ (\inp expbn expdn -> TestLabel inp $ TestCase $ assertEqual inp expdn (dirname inp))
+
+tcatFrom =
+ [cmdcase "basic" foo $ catFrom [fn],
+ cmdcase "twice" (foo ++ foo) $ catFrom [fn, fn],
+ cmdcase "-,foo" ("hi\n" ++ foo) $ "echo hi" -|- catFrom ["-", fn],
+ cmdcase "foo,-" (foo ++ "hi\n") $ "echo hi" -|- catFrom [fn, "-"],
+ cmdcase "foo,-,cat" " 1\t1234\n 2\t5678\n 3\t14\n 4\thi\n"
+ $ "echo hi" -|- catFrom [fn, "-"] -|- "cat -n",
+ cmdcase "bytes" foo $ catFrom [fn] -|- catBytes Nothing
+ ]
+ where fn = "testsrc/testdata/foo"
+ foo = "1234\n5678\n14\n"
+
+techo =
+ [cmdcase "basic" s $ echo s,
+ cmdcase "shcat" s $ echo s -|- "cat",
+ cmdcase "cat" s $ echo s -|- catFrom ["-"]
+ ]
+ where s = "testfoobarbaz"
+
+tcatTo = [] -- FIXME: write
+
+tcd =
+ [TestCase $
+ do p <- pwd
+ cd "testsrc"
+ p2 <- pwd
+ assertEqual "after cd" (p ++ "/testsrc") p2
+ cd ".."
+ p3 <- pwd
+ assertEqual "after cd .." p p3
+ ]
+
+tgreps =
+ [tc "oo" (isInfixOf "oo") (grep "oo") (grepV "oo"),
+ tc "nonexistant" (\_ -> False) (grep "nonexistant")
+ (grepV "nonexistant"),
+ tc "e ^oo" (isPrefixOf "oo") (egrep "^oo") (egrepV "^oo"),
+ tc "e nonexistant" (\_ -> False) (egrep "nonexistant") (egrepV "nonexistant")
+ ]
+ where tc name filtfunc cmd cmdv = TestLabel name $ TestCase $
+ do c <- readFile "testsrc/testdata/quux"
+ let exp = unlines . filter filtfunc . lines $ c
+ let expv = unlines . filter (not . filtfunc) . lines $ c
+ r <- run (catFrom ["testsrc/testdata/quux"] -|- cmd)
+ assertEqual "grep" exp r
+ r2 <- run (catFrom ["testsrc/testdata/quux"] -|- cmdv)
+ assertEqual "grepv" expv r2
+
+twcL =
+ [t "null" 0 ("echo", ["-n", ""]),
+ t "empty" 1 ("echo", [""]),
+ t "no eol" 1 ("echo", ["-n", "foo"]), -- shell does 0 here; which is right?
+ t "normal" 1 "echo foo",
+ t "quux" 100 (catFrom ["testsrc/testdata/quux"])]
+ where t name expint cmd =
+ cmdcase name ((show expint) ++ "\n") (cmd -|- wcL)
+
+tests = TestList
+ [tl "abspath" tabspath,
+ tl "basename" tbasename,
+ tl "dirname" tdirname,
+ tl "catFrom" tcatFrom,
+ tl "echo" techo,
+ tl "catTo" tcatTo,
+ tl "cd" tcd,
+ tl "grep family" tgreps,
+ tl "wcL" twcL
+{-
+ -- tl "pwd" tpwd, -- covered by tcd
+ tl "readlink" treadlink,
+ tl "tee" ttee -}
+ ]
+ where tl x y = TestLabel x $ TestList y
+
--- haskell-hsh-2.0.3.orig/testsrc/TestUtils.hs
+++ haskell-hsh-2.0.3/testsrc/TestUtils.hs
@@ -0,0 +1,29 @@
+{-
+Copyright (C) 2004-2007 John Goerzen <jgoerzen@complete.org>
+Please see the COPYRIGHT file
+-}
+
+module TestUtils where
+import Test.HUnit
+import HSH
+
+{- | Run each test three times in an attempt to check for race conditions
+or nondeterministic behavior. Not perfect, but it could help anyhow. -}
+
+testcmd expected cmd =
+ [tc "run1", tc "run2", tc "run3"]
+ where tc runno = TestLabel runno $ TestCase $ do
+ r <- run cmd
+ assertEqual "run result" expected r
+
+{-
+testcmd expected cmd =
+ do r <- run cmd
+ r2 <- run cmd
+ r3 <- run cmd
+ assertEqual "expected" expected r
+ assertEqual "run 2" expected r2
+ assertEqual "run 3" expected r3
+-}
+
+cmdcase name expected cmd = TestLabel name $ TestList (testcmd expected cmd)
--- haskell-hsh-2.0.3.orig/testsrc/Tests.hs
+++ haskell-hsh-2.0.3/testsrc/Tests.hs
@@ -0,0 +1,15 @@
+{-
+Copyright (C) 2004-2007 John Goerzen <jgoerzen@complete.org>
+Please see the COPYRIGHT file
+-}
+
+module Tests(tests) where
+import Test.HUnit
+import qualified Core
+import qualified ShellEquivsTest
+
+test1 = TestCase ("x" @=? "x")
+
+tests = TestList [TestLabel "test1" test1,
+ TestLabel "core" Core.tests,
+ TestLabel "ShellEquivs" ShellEquivsTest.tests]
--- haskell-hsh-2.0.3.orig/testsrc/Core.hs
+++ haskell-hsh-2.0.3/testsrc/Core.hs
@@ -0,0 +1,102 @@
+{-
+Copyright (C) 2004-2007 John Goerzen <jgoerzen@complete.org>
+Please see the COPYRIGHT file
+-}
+
+module Core(tests) where
+import Test.HUnit
+import Test.HUnit.Tools
+import HSH
+import HSH.ShellEquivs
+import TestUtils
+import Data.Char
+import Control.Exception
+import qualified Data.ByteString.Lazy as BSL
+
+basics =
+ [cmdcase "echo" "hi\n" $ "echo hi",
+ cmdcase "echo as args" "there\n" $ ("echo", ["there"]),
+ cmdcase "more args 1" "100 testsrc/testdata/quux\n"
+ "wc -l testsrc/testdata/quux",
+ cmdcase "more args 2" "100 testsrc/testdata/quux\n"
+ ("wc", ["-l", "testsrc/testdata/quux"])
+ ]
+
+pipes =
+ [cmdcase "sh2sh" "100\n" $ "cat testsrc/testdata/quux" -|- "wc -l",
+ cmdcase "sh2sh2sh" "14\n" $
+ "cat testsrc/testdata/quux" -|- "grep oo" -|- "wc -l",
+ cmdcase "sh2sh2sh2sh" "0000000 061 064 012\n0000003\n" $
+ "cat testsrc/testdata/quux" -|- "grep oo" -|- "wc -l" -|- "od -b",
+ cmdcase "ls baseline" lsbase lscmd,
+ cmdcase "sh|s->s" (map toUpper lsbase) $ lscmd -|- (map toUpper),
+ cmdcase "sh|s->s|sh" "BAR\nBAZ\n" $
+ lscmd -|- (map toUpper) -|- "grep BA",
+ cmdcase "sh|s->s|s->s" "BAR\nBAZ\n" $
+ lscmd -|- (map toUpper) -|- grep "BA",
+ cmdcase "s->s|sh" (map toUpper lsbase) $ echo lsbase -|- "tr a-z A-Z",
+ cmdcase "s->s|sh|sh" "BAR\nBAZ\n" $
+ echo lsbase -|- "tr a-z A-Z" -|- "grep BA",
+ cmdcase "s->s|sh|sh BS" (str2bs "BAR\nBAZ\n") $
+ echo lsbase -|- "tr a-z A-Z" -|- "grep BA",
+ cmdcase "BS s->s|sh|sh" "BAR\nBAZ\n" $
+ echo lsbaseBSL -|- "tr a-z A-Z" -|- "grep BA",
+ cmdcase "BS s->s|sh|sh BS" (str2bs "BAR\nBAZ\n") $
+ echo lsbaseBSL -|- "tr a-z A-Z" -|- "grep BA",
+ cmdcase "s->s|sh|s->s" "BAR\nBAZ\n" $
+ echo lsbase -|- "tr a-z A-Z" -|- grep "BA",
+ cmdcase "BS s->s|sh|s->s" "BAR\nBAZ\n" $
+ echo lsbaseBSL -|- "tr a-z A-Z" -|- grep "BA",
+ cmdcase "s->s|s->s|sh" "BAR\nBAZ\n" $
+ echo lsbase -|- (map toUpper) -|- "grep BA",
+ cmdcase "BS s->s|s->s|sh" "BAR\nBAZ\n" $
+ echo lsbaseBSL -|- (map toUpper) -|- "grep BA",
+ cmdcase "s->s|s->s|s->s" "BAR\nBAZ\n" $
+ echo lsbase -|- (map toUpper) -|- grep "BA",
+ cmdcase "BS s->s|s->s|s->s" "BAR\nBAZ\n" $
+ echo lsbaseBSL -|- (map toUpper) -|- grep "BA",
+ cmdcase "true" "0\n" $ "true" -|- "wc -l",
+ cmdcase "true|true" "" $ "true" -|- "true",
+ cmdcase "shell" "testsrc/testdata/bar\ntestsrc/testdata/baz\ntestsrc/testdata/foo\ntestsrc/testdata/quux\n" "ls testsrc/testdata/*"
+ ]
+ where lsbase = "bar\nbaz\nfoo\nquux\n"
+ lsbaseBSL = str2bs lsbase
+ lscmd = "ls testsrc/testdata"
+ str2bs = BSL.pack . map (fromIntegral . fromEnum)
+
+sleeptests =
+ [cmdcase "sleep 0.10" "" "sleep 0.10",
+ cmdcase "sleep|true" "" $ "sleep 0.10" -|- "true",
+ cmdcase "true|sleep" "" $ "true" -|- "sleep 0.10",
+ cmdcase "true|sleep|true" "" $ "true" -|- "sleep 0.10" -|- "true"
+ ]
+
+errortests =
+ [errcase "ls" "(\"false\",[]): exited with code 1"
+ ("false", []::[String]),
+ errcase "false|true" "(\"false\",[]): exited with code 1" $
+ ("false", []::[String]) -|- "true",
+ errcase "true|false" "(\"false\",[]): exited with code 1" $
+ "true" -|- ("false", []::[String]),
+ errcase "sh80" "(\"sh\",[\"-c\",\"exit 80\"]): exited with code 80" $
+ ("sh", ["-c", "exit 80"]),
+ cmdcase "bfalse" False "false",
+ cmdcase "btrue" True "true",
+ cmdcase "b80" False ("sh", ["-c", "exit 80"]),
+ cmdcase "i80" (80::Int) ("sh", ["-c", "exit 80"]),
+ cmdcase "i0" (0::Int) "true",
+ cmdcase "i1" (1::Int) "false"
+ ]
+ where errcase name exp cmd =
+ TestLabel name $ TestCase $
+ do assertRaises "runS" (userError exp)
+ ((run cmd)::IO String)
+ assertRaises "run" (userError exp)
+ ((run cmd)::IO ())
+
+tests = TestList
+ [TestLabel "basics" $ TestList basics,
+ TestLabel "pipes" $ TestList pipes,
+ TestLabel "errors" $ TestList errortests,
+ TestLabel "sleep" $ TestList sleeptests]
+
--- haskell-hsh-2.0.3.orig/testsrc/testdata/quux
+++ haskell-hsh-2.0.3/testsrc/testdata/quux
@@ -0,0 +1,100 @@
+Sha%e8ae
+Tho2cot|
+Oot_oo4b
+mai#P2ee
+Mo1IeW#i
+ioQu3Io.
+ooL8ca:z
+Li4Roop>
+Al/ie2th
+Pe=u8hie
+shi@ci9W
+Ud8Nah?r
+we6uoS}u
+Xa3ing]i
+Wa|G{uo0
+Xa)e3wa{
+bo*Ngi0M
+ee%w1ieC
+ka8ai}D:
+zo@f7aiZ
+jio}W3ae
+eiHie:n7
+Rie'zo9F
+di@x6Osh
+ahn3Jo%f
+ieSh;oi2
+fahM(oh9
+thieX]a8
+Ii_nooj4
+Kub6ail^
+ri2uPi*m
+Au%Zae1o
+oCh{oov8
+of?a8Eth
+ie4ooS|o
+aiD6dai}
+da9Du]ch
+zee)f1Ae
+Joh2Ta@x
+AeS$ai4a
+aiD$oe6i
+esh$e3Ie
+iG]awei3
+Ahk@ei8i
+Hae+Jio2
+PaeS[ai3
+zoh^Yae8
+na_D9no8
+Ic.oop1I
+aim8Ea!h
+Et9oi%ci
+So5ki{za
+woh,qu8F
+eJ0eej_u
+Ta5seiv;
+Ah!i7oip
+shu2Uo\y
+cha1Aik|
+coo%Z4ye
+xie^F^u2
+eiJ+oam9
+ohC7ox}a
+Ahch8pe:
+EuNo$m5H
+Vo5thi}p
+ei)b9aeG
+ju~v2Noo
+jio4Oa[f
+Kai<j;i7
+Lao?ng9v
+iequ_uL0
+EC2aeng^
+aen9tuT{
+Doh5Ui;n
+oov(ae4B
+coo?c1Ta
+ohdai.P4
+Shei)ph6
+Ooyo9bu=
+Ahh!ah1O
+ii:jo7Ai
+Fei~r3fo
+Loo]vae3
+mai[Ci4x
+Soh%a7oh
+naiB9wu%
+pa]XooG6
+Wee!r6ae
+Ohf>it7u
+aze%j8Ai
+uipoh{F1
+oozo5oN}
+EeSe|f3g
+aey$o0Ai
+Ohph`oh2
+piPh]oh5
+EiH7ou#L
+xue5Oi%d
+uu<Y\ah2
+UR1uboi@
--- haskell-hsh-2.0.3.orig/testsrc/testdata/bar
+++ haskell-hsh-2.0.3/testsrc/testdata/bar
@@ -0,0 +1,13 @@
+eC;aew4s Ee4apha. AW5ao[xe Ag0etai. aeX~ae0r eo;d5AeN aN3te'du bu2Koh\l
+ahh#o1Xi eiR-ie8u Aino&ph6 ee|n6Cha Fe]vuh3E Ce@ghai6 ahw5iuX! tai^D7xe
+EeNoo+n6 NeiV5Ti_ Pie,ph5s Loxie@d5 ohCh|ah6 Wee8wa*e xoo6eiL[ to?Thu0h
+ieD=ahv2 xohC+ah9 Ea>m%ui3 Kae[K7ug eic,u4Du Fom3pee{ oThoo&r8 Ieng3ti;
+neiDi>o5 aiM8iu)S ka0eYai# Se7iev$e Mee7agh_ Coy|eik9 aa=Chae1 veeH5ii#
+eej1Cha< sahZ{ai8 du6Pi>fi wu(T5Ohb Ieph^ie4 eet0Wae[ AiMo{u1t ov`i7ahG
+oa9eNgo: ieB)oh2y Ei7ahj!a Quo2equ@ Oow7Fai` laa,g6Eu Chie4ev# ji-f8Phu
+EWoh+Me4 UC2yax@o OeD+oo0d faLi\u3o un>ool4Z yai5Iu:f Al3Ahke` eQu_ij2o
+iV1To#wo xa7Aep$a Thob%ee4 chii_f1D Shu8kie| Ej0Doh<p cif-ee1E bah/So7o
+iepi)W4k nei_ph7I ier4See( vae_h1Ee ha)aT4zi EiF6OoP` aiK_oh2l Aem5jei;
+aW]ooX6a Caim'ei1 shee8Ui~ jo+uJ2se kie3Ah}o Ohcoh-R1 ux)oo4Og Si0tah>j
+oshoa;G1 iel#ae0B kei3Xee) IaL7Oon| Ohs_iaD1 Lu@p7ath uh[u4waJ Ahwah$v4
+Yu3woh!p tha5Ge&x Yei%ko2a eeG2uo<f
--- haskell-hsh-2.0.3.orig/testsrc/testdata/foo
+++ haskell-hsh-2.0.3/testsrc/testdata/foo
@@ -0,0 +1,3 @@
+1234
+5678
+14
--- haskell-hsh-2.0.3.orig/testsrc/testdata/baz
+++ haskell-hsh-2.0.3/testsrc/testdata/baz
@@ -0,0 +1,15 @@
+tha1oe*R Xu6Deew, aeM)eix6 ooM)oh7I Koow}a6L poo!l4uV To3eiv\i hie%J2ku
+koh&M5sh AeG8phu> jieJ0Wo@ aey\aK1u phee+B3t zae-g2Ui utuF$i9c di=ej2Ru
+eiGoh*S9 en-ohSh5 Pok6li_g ra5UuHe/ xu,iG0di lus8Dae& Aivai`m8 eeGh(ai5
+aTh3oyi" Dee0aiN$ ie\N4tho eiS@ae6z ieJ9ko`n Jao[x2re mudi]f8V ho.C1chi
+Tha1bei| Ood2ohB? eK=ief4e Le_po<a5 Poow]ag4 aiz<eeW4 ooch\u9E EiN=ee1n
+nee<D6ij gihu'Vu7 ohB,euf9 xe-qu1Ku ahZ1nu,e iet8Mei[ vee<Phu3 Ka.x&ee9
+Xoe*j4fi Ong0ooY` oof0Ue@y Uaqu6og- sae|H8ja Joh3oa"n ahY\ae1g io_l8Ieh
+mie7Pao] Ohx}ohf4 ohb'ahT1 ga&Pei0o La]Ng6ae opu;ed1E yoh'Y7ma eej+ai8H
+EiGh0ec/ pe3Phei< Poo'c8ee UK6See(v uo5cai.M ohK~i0ya Awie9wo} quoo?L5s
+Ca%k5Coo Ciik1uW< reeK9it+ aPhe&ph8 AhL3uZ-o eis4Lai, Es%eoj7i eew4Ahn/
+VoNg2mu) ni<R8she Wei,ng9o iva_d4Yu be2iu-Th mi?raeZ0 eeP7poh$ Tei}ph3O
+voo,H2ae eeJui:f4 eN^ie4aa Gaib(ee0 Ce0kahd/ ahmoh]N6 ieK5De~a Ohgh_ae8
+mei%k0Ku Fas5Au<g Nuv1ohs^ fae:woH1 Joh!Gh6m ruo3Ko]h Du3ahpu( shei=B1B
+We|Y5suW io,l9Fun Igh7Noh$ yah<c0Ai hash;o2A aeQu/ae1 Ooy2sie] bu$jee6A
+Mi7thei{ ei6Chie/ ath=oh3I nooz7oV* Taj%ah0d ea7Uk'ei pash3Xe] aC4ar[ai