From 52ac60af8132ae7e42151d3012a9607d7cadaf95 Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Thu, 11 Oct 2007 21:16:28 +0000 Subject: [PATCH] Tested each sample. --- gem/ex1.lua | 4 + gem/ex10.lua | 17 +++ gem/ex11.lua | 7 + gem/ex12.lua | 34 +++++ gem/ex2.lua | 11 ++ gem/ex3.lua | 15 ++ gem/ex4.lua | 5 + gem/ex5.lua | 15 ++ gem/ex6.lua | 14 ++ gem/ex7.lua | 16 +++ gem/ex8.lua | 5 + gem/ex9.lua | 3 + gem/gem.c | 54 +++++++ gem/gt.b64 | 206 +++++++++++++++++++++++++++ gem/input.bin | Bin 0 -> 11732 bytes gem/ltn012.tex | 351 +++++++++++++++++++++++++--------------------- gem/luasocket.png | Bin 0 -> 11732 bytes gem/makefile | 9 ++ gem/t1.lua | 25 ++++ gem/t1lf.txt | 5 + gem/t2.lua | 36 +++++ gem/t2.txt | 4 + gem/t2gt.qp | 5 + gem/t3.lua | 25 ++++ gem/t4.lua | 10 ++ gem/t5.lua | 30 ++++ gem/test.lua | 46 ++++++ 27 files changed, 789 insertions(+), 163 deletions(-) create mode 100644 gem/ex1.lua create mode 100644 gem/ex10.lua create mode 100644 gem/ex11.lua create mode 100644 gem/ex12.lua create mode 100644 gem/ex2.lua create mode 100644 gem/ex3.lua create mode 100644 gem/ex4.lua create mode 100644 gem/ex5.lua create mode 100644 gem/ex6.lua create mode 100644 gem/ex7.lua create mode 100644 gem/ex8.lua create mode 100644 gem/ex9.lua create mode 100644 gem/gem.c create mode 100644 gem/gt.b64 create mode 100644 gem/input.bin create mode 100644 gem/luasocket.png create mode 100644 gem/t1.lua create mode 100644 gem/t1lf.txt create mode 100644 gem/t2.lua create mode 100644 gem/t2.txt create mode 100644 gem/t2gt.qp create mode 100644 gem/t3.lua create mode 100644 gem/t4.lua create mode 100644 gem/t5.lua create mode 100644 gem/test.lua diff --git a/gem/ex1.lua b/gem/ex1.lua new file mode 100644 index 0000000..327a542 --- /dev/null +++ b/gem/ex1.lua @@ -0,0 +1,4 @@ +local CRLF = "\013\010" +local input = source.chain(source.file(io.stdin), normalize(CRLF)) +local output = sink.file(io.stdout) +pump.all(input, output) diff --git a/gem/ex10.lua b/gem/ex10.lua new file mode 100644 index 0000000..2b1b98f --- /dev/null +++ b/gem/ex10.lua @@ -0,0 +1,17 @@ +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then return 1 + else return nil, src_err or snk_err end +end + +function pump.all(src, snk, step) + step = step or pump.step + while true do + local ret, err = step(src, snk) + if not ret then + if err then return nil, err + else return 1 end + end + end +end diff --git a/gem/ex11.lua b/gem/ex11.lua new file mode 100644 index 0000000..1cbf01f --- /dev/null +++ b/gem/ex11.lua @@ -0,0 +1,7 @@ +local input = source.chain( + source.file(io.open("input.bin", "rb")), + encode("base64")) +local output = sink.chain( + wrap(76), + sink.file(io.open("output.b64", "w"))) +pump.all(input, output) diff --git a/gem/ex12.lua b/gem/ex12.lua new file mode 100644 index 0000000..de17d76 --- /dev/null +++ b/gem/ex12.lua @@ -0,0 +1,34 @@ +local smtp = require"socket.smtp" +local mime = require"mime" +local ltn12 = require"ltn12" + +CRLF = "\013\010" + +local message = smtp.message{ + headers = { + from = "Sicrano ", + to = "Fulano ", + subject = "A message with an attachment"}, + body = { + preamble = "Hope you can see the attachment" .. CRLF, + [1] = { + body = "Here is our logo" .. CRLF}, + [2] = { + headers = { + ["content-type"] = 'image/png; name="luasocket.png"', + ["content-disposition"] = + 'attachment; filename="luasocket.png"', + ["content-description"] = 'LuaSocket logo', + ["content-transfer-encoding"] = "BASE64"}, + body = ltn12.source.chain( + ltn12.source.file(io.open("luasocket.png", "rb")), + ltn12.filter.chain( + mime.encode("base64"), + mime.wrap()))}}} + +assert(smtp.send{ + rcpt = "", + from = "", + server = "localhost", + port = 2525, + source = message}) diff --git a/gem/ex2.lua b/gem/ex2.lua new file mode 100644 index 0000000..94bde66 --- /dev/null +++ b/gem/ex2.lua @@ -0,0 +1,11 @@ +function filter.cycle(lowlevel, context, extra) + return function(chunk) + local ret + ret, context = lowlevel(context, chunk, extra) + return ret + end +end + +function normalize(marker) + return filter.cycle(eol, 0, marker) +end diff --git a/gem/ex3.lua b/gem/ex3.lua new file mode 100644 index 0000000..a43fefa --- /dev/null +++ b/gem/ex3.lua @@ -0,0 +1,15 @@ +local function chainpair(f1, f2) + return function(chunk) + local ret = f2(f1(chunk)) + if chunk then return ret + else return (ret or "") .. (f2() or "") end + end +end + +function filter.chain(...) + local f = select(1, ...) + for i = 2, select('#', ...) do + f = chainpair(f, select(i, ...)) + end + return f +end diff --git a/gem/ex4.lua b/gem/ex4.lua new file mode 100644 index 0000000..c670e0e --- /dev/null +++ b/gem/ex4.lua @@ -0,0 +1,5 @@ +local qp = filter.chain(normalize(CRLF), encode("quoted-printable"), + wrap("quoted-printable")) +local input = source.chain(source.file(io.stdin), qp) +local output = sink.file(io.stdout) +pump.all(input, output) diff --git a/gem/ex5.lua b/gem/ex5.lua new file mode 100644 index 0000000..196b30a --- /dev/null +++ b/gem/ex5.lua @@ -0,0 +1,15 @@ +function source.empty(err) + return function() + return nil, err + end +end + +function source.file(handle, io_err) + if handle then + return function() + local chunk = handle:read(20) + if not chunk then handle:close() end + return chunk + end + else return source.empty(io_err or "unable to open file") end +end diff --git a/gem/ex6.lua b/gem/ex6.lua new file mode 100644 index 0000000..a3fdca0 --- /dev/null +++ b/gem/ex6.lua @@ -0,0 +1,14 @@ +function source.chain(src, f) + return function() + if not src then + return nil + end + local chunk, err = src() + if not chunk then + src = nil + return f(nil) + else + return f(chunk) + end + end +end diff --git a/gem/ex7.lua b/gem/ex7.lua new file mode 100644 index 0000000..c766988 --- /dev/null +++ b/gem/ex7.lua @@ -0,0 +1,16 @@ +function sink.table(t) + t = t or {} + local f = function(chunk, err) + if chunk then table.insert(t, chunk) end + return 1 + end + return f, t +end + +local function null() + return 1 +end + +function sink.null() + return null +end diff --git a/gem/ex8.lua b/gem/ex8.lua new file mode 100644 index 0000000..81e288c --- /dev/null +++ b/gem/ex8.lua @@ -0,0 +1,5 @@ +local input = source.file(io.stdin) +local output, t = sink.table() +output = sink.chain(normalize(CRLF), output) +pump.all(input, output) +io.write(table.concat(t)) diff --git a/gem/ex9.lua b/gem/ex9.lua new file mode 100644 index 0000000..b857698 --- /dev/null +++ b/gem/ex9.lua @@ -0,0 +1,3 @@ +for chunk in source.file(io.stdin) do + io.write(chunk) +end diff --git a/gem/gem.c b/gem/gem.c new file mode 100644 index 0000000..976f74d --- /dev/null +++ b/gem/gem.c @@ -0,0 +1,54 @@ +#include "lua.h" +#include "lauxlib.h" + +#define CR '\xD' +#define LF '\xA' +#define CRLF "\xD\xA" + +#define candidate(c) (c == CR || c == LF) +static int pushchar(int c, int last, const char *marker, + luaL_Buffer *buffer) { + if (candidate(c)) { + if (candidate(last)) { + if (c == last) + luaL_addstring(buffer, marker); + return 0; + } else { + luaL_addstring(buffer, marker); + return c; + } + } else { + luaL_putchar(buffer, c); + return 0; + } +} + +static int eol(lua_State *L) { + int context = luaL_checkint(L, 1); + size_t isize = 0; + const char *input = luaL_optlstring(L, 2, NULL, &isize); + const char *last = input + isize; + const char *marker = luaL_optstring(L, 3, CRLF); + luaL_Buffer buffer; + luaL_buffinit(L, &buffer); + if (!input) { + lua_pushnil(L); + lua_pushnumber(L, 0); + return 2; + } + while (input < last) + context = pushchar(*input++, context, marker, &buffer); + luaL_pushresult(&buffer); + lua_pushnumber(L, context); + return 2; +} + +static luaL_reg func[] = { + { "eol", eol }, + { NULL, NULL } +}; + +int luaopen_gem(lua_State *L) { + luaL_openlib(L, "gem", func, 0); + return 0; +} diff --git a/gem/gt.b64 b/gem/gt.b64 new file mode 100644 index 0000000..a74c0b3 --- /dev/null +++ b/gem/gt.b64 @@ -0,0 +1,206 @@ +iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAtU0lEQVR42u19eXRURdb4rarXa5LO +RshKEshC2MLOBIjsCoMLGJhRPnUEcUGZEX7j4Iw6zqd+zjkzzowL6gzKMOoBRHAAPyQKUZQlxLAk +EIEkQkhCyEoISegs3f1eVf3+qPTj0Z3udEJImN/Pe/rkdF6/V6/q3qp7b92tEOccfoT+A9zfHfj/ +HX4kQD/DjwToZ/iRAP0MPxKgn+FHAvQz/EiAfgapvzvQQ3DfviCE+rtTPYH/AAKouEYIcc4ForUX +tXeKexhj6k8IIe2DvdUl0SYAcN7RGYQ63oAQ4hx8fBu6BXfC6vBcsHyDeNRi7cYboZQjBIRgl/lB +KQcAQnyl+q1IAC9YU7/s2bOnsrKSUupwOHQ63cMPP2wymRhjGOOrV6/m5ORYLJbg4OABAwZYLBaD +waBtQUsD34mqRT0hHc/abEpNjbWlxYEQCgw0RET463QEABjjjHFfyND/LEg737XsQpblhoaGioqK +CxcunD9/fv78+ampqepgZFk2mUwBAQEYY6PRSAhRG7Tb7cXFxXa73W63W63Wn/zkJ4sXL1YfVHGB +EFI5VZc0EDcwxjnnkoRbWhw7dxZt316Yn19TW9siyxQADAZddHRAWlrMffeNnDcvUa8nlDKEAGNv +7ffbClCnoYoFFRFiIufn53/88cfBwcERERERERHjxo2LjIz0ZbaqFLXb7ZcuXZIkKSoqShAYY7xn +z576+vpJkybFxcUZjUZfOJKKfQBACP75z/yXXtpfXX0JAAFIAAQAAXAADsAAZAA0dGjMa6/Nueee +FEoZQsgLDfqTAFqWIstyRUVFXFycJEniJ6vV2tTUFBUVRQhxkb0q2TTS7xr9tNxG/bdjtAjl5eXl +5ubW1dUhhJKTkzMyMkwmk0p4AMAYq91Tv1DKCMENDW0PPLBj797vEdJjrAfgjF2HP+d8B8YcAMry +5VP//vf5Oh3h3OM66P8V0NTU9N133+Xl5SmKsnr16qCgIBc8MsbE5HXXgjqdU9oRie8YY5c2W1tb +CwsLS0tLFy5cqEoILWnFI84rHGNUXW29/fYPCwsvSpI/pQLxntYNxxhjDIpinTNn1K5d/2Uy6Zwd +cNWO+o4A7mjFGOfk5OzcuTMsLGzixInjxo2zWCwqIlSpAL2k47tMc+18FN8vXLgAAHFxce4Cqa1N +njlzw9GjZZLkryiK6KP3twEgnY7I8tWf/WzCtm33McZVJVV7H3nppZf6BvXaL+rAFEVJSEhYvHjx +4MGDDQaDykxAw1h6S38XLxUcRnRGnXyiM4cOHdqyZUtDQ0N0dLSfn5/4SUz/Z57Zs3PnCZ0uQFEU +ANQV9jvIwxiTJOPp0xdCQgLS0gZRyjF2Hc5NXwEu866lpUWv1+v1enVBqFsnwWS0dLrZ4K7dlpSU +ZGZmVlVVpaen33PPPYL1HzlSOXnyewCk+6gSo2OhocaCgl9GR1vEOtCO7qbbglQsY4yPHj366quv +nj59GjScWtBGq0f2mVHBZbVxzhMSElatWvXzn//cORUAANau/Y5zB8YYoLsUQJxzQqSGhqb1648D +gFClXO+4eSNUZ9alS5e2b99eXl4+d+7cqVOnCrl361hvOt2LCNWlttY6bNjbTU22Hk9WhBDnjhEj +IgoKVoqdc1+vAFmW//WvfymK8uyzz86aNUvlP72HPrjBWaR2RkgIoXeJ2ZqbW9nUdBVj0uPGOecA +ujNn6s+cuQRui6CXd8JaJUedSsJUEBoaqtfrtdd9p4HQ3rTGL9UE1ik2BZ/trmnMRePinAFAQUEt +AMMYuXMP34EQRKnjzJlLqakRLr3uTQJoJarLzigyMpIxJiStVr/0pTXOQdgAMEaEYACOEPb+tKCU +UOEVhYq9qKCKTwYyzW0XL169cUaNEAJglZVXwc2Q3msE0GKfEFJYWGg2m+Pj41UtyMeJr8W7olCB +dFVS2mxKZeXVqqqrFRXN9fVtDQ1tbW2yw0EBQK8nJpNuwABTWJjfoEGB0dEBMTEWk0mHEBYPU8oY +Y04S+roEbTalt1Bkt1P3i728AjjnhJCjR49u3rw5IyNDEACcvBW8ajgqRhSFCUsvQhghVF/fmptb +efjwxWPHqs6da6iutlLqAFA86yQIQCJEHxkZkJQUMnFi9JQpg9LSYsLD/THusCtw3mHR7JIMfn66 +3sKP2dxJU70sAzDGBw4c2Llz5/333z958mRVqfD+lBb1GCNhxa2oaP788x8++6z4yJFKq9UKQAGI ++CCkw1jvqVkhPylllZVXKivrv/22EID4+wdMmhS9YEHKggVD4+KCxAqjlHkig9DfASA+PkismO7r +oNeAMQ6A4+ODwG0K9o4aqtoajx07tnnz5mXLlo0ePVplO12iXhjZMUYYI1mme/aUrF+f/9VXJTZb +CwAG0GFMhDHLxfjlHQTTF/KTMQogAzCDwW/27ITHHhs/f36SXk+8GO4VhUkSzsoqmTv3XxgbbkQI +A3BJQmfO/DI5eYAQhL1JAK0l68qVK1euXElMTOyS6av6EqViI4bb2+WNGwveeCO3uLgSAAAMhBCA +Dh/TjQMhCABRSgHsAJCUFL16ddrDD4/289OrfQDNahBGiKYm2/Dha2tqrAj1YCcMAIAxYsw+aVLs +kSMr3G2IN7QPcOqFXJ3IISEhCQkJvmBfaIeKIqQifPDBiREj3n3iiW3FxTUYmwgxCWT1FvYBgFJO +KQVAhJgwNp07V7ty5afDh7+7fn0e50AIVhTGmNZiCIrCgoKMixYNB7D3aCcMTvalPPjgGNEHl597 +vgI8Gd8FL/JkLnaf+IcPV6xatScv7zxCEsYGdQd0k6HDvs2Yg3PH6NFD3npr3vTp8Wqv1D0Hxqik +5MrYse+0tFCn48X3LSTHGDMmJySEnDjxy4AAfa+tAK1yWVpampubqxJDMLhOub9W2BKC29uVX/7y +i/T09/LyygjxQ0hPKe0T7AMAYoxTShGSCPEvKKiYMWP9E0/sbm11iKXgHAIoCktMDHnxxVkAbTpd +t9DFnahW/vSneQEBHYzOBS09IYA62THGra2tmzZtOnfunO9PCeF25Ejl+PHr3n13PyE6jI1O1Pex +dQgxBpRSjA2E6N9//+DYseuysyskCVPKBTsiBDHGn302ffHiCbJs1ekkJ3K7GC5CSKfDlFrXrJm1 +ePFwShnGnYyuJwTQ+vk2bdrk5+e3ZMkS9Scv2GeMU8p1OvLOO0enTn3v7Nk6QvwpFQbRfjTMIcYY +pZwQ/9LS+mnT3n/99e8kCQtmKNYB53zTpkV33jlGlpslSWzIPZFBhKUQjLksW596auZrr92hYt8d +Pz1cAQKhmZmZpaWlS5culSRJsKNOJYrWqY0xeuKJz3/1q38DYIz1lIrNYT9gHyFXAxGlFGM9xtIz +z+xctuwzYUESXnXOQacj//u/S3796zsUxU6pDSGQJEKIsHB0fAhBkkQQ4pS2Ygyvv77o3XfvFNjv +zagIVZLs27cvMDBwwoQJqpHHE98Xno3WVvlnP9v65ZcFkhSgKKybAu0GgQMgse2iVIQviIFjjDHG +YnvccZskYUWxzp49cseO+y0Wg+i82DFIEj58uOL55/cdPFgKYHfuDcUoGAAFYISY77572B//OGv4 +8DBFYd6jg3pIAE8hCF6w39xsu+uuTdnZZyXJv2+x34F6xhjndgAOoPfzM5nNEqXcarXLsg1AAdBh +rIcOB5GgQcukSQlffPGL0FCTGIJgSmI65+VV79xZnJNzsby8UQ3MSkgImT49PiNjWHJyqBrC5d3u +1A0CuHstvOv7KufBGFmtjnnzPsrJKZEkP0WhfTnxnV1t0+mMs2YlLVyYMnFiVHS0xWzWUcqammzn +zl359tuyf/+7sKSkGiEJIT1jFAAkiShK68SJg7OylgYFGcVAAECrqiKEZJm2tysIgdmsc14EWRY2 +FY/q+A0RQG3Re2yIerMsszvv3Pj114WS5N/n2McACufKz38+/uWXZ6SkDHDvs4rH7duLXnjh69LS +GkLMlHIALmgwbVry3r0PGwwd4T3gNDcJkqiUUC8SgjEWPoyuba6+CmFtAMH+/ftra2s7COjVuim0 +iEcf/axfsI8x5twRGGjYufPhrVsXJyeHUsrEdlf7oZTLMiUE33//yFOnVj7yyBRK2wgBAKQoVJL8 +Dh78YenSHerqV13cOl2HhUr1DmGMdDpSX3/p22/3C1+3FnU3RAC1obNnz+7atau9vd1L007WzwnB +r756YOPGI/0y9xmTo6IsBw8+vnBhiixT4dIRWNN+CEE6HRF7LoOBbNiw4JVX5lNqwxg5aeC/deux +F1/cRwimVJV/AM79ppAK6opvb2/ftWtXSUlJl9iHbsUFiXds2rQpOTl52rRpnoydzoAfJkk4M/Ps +Y4/twNjotIH0ndQFYP7+ur17l40ZEyHLVJKwpy26+q/Q7hWFzZw5uKVFyck5R4gwjQDGhgMHzqam +Ro8YMVBs472YuYKDg69cuVJQUJCWlubi5nQHn1aAuu5OnDhRU1MzZ84c7/cLda2mpuWJJz4DQJx3 +14Ryo4AxAnC8+ead48dHORxUhIx7R4Rzb48IwYyx116bm56eRGm7sMFxDgDSU0/9b0VFsyRhL/YS +8Yrbb7+9trY2Ly9Pxd4NEUCFc+fOTZgwYeDAgWL6u9+g2kcB4Omnd1dVNRCi57wvN7rC/mWbNWvo +8uXjKWU6He5SErrQQAjb116bCyAJAwnnjBBdXV3jr36122WY7sAYCwsLGz9+vOBCXbzURy3Iydap +oijafIfr7+kw4UoS3rLl1H/912ZCTJT2tZkBIcS5PTNz6fz5yaIzvicMqWillEsSzsjYsnNnASEm +oRQRgilt+/DD+x9+eKyzZe6GhA7M2O12Qoga7O3pdb6yIPEXY+w1qodzziUJNzXZXnghC0ByKgJ9 +BxgD546UlIjbb08AAEKuCUwfQTu0hx4aDYDUKcoYB9D9/vdfX77c5oURiZWk1+tFYD14FcVdEECr +fbq8wH36g9Ph8Ne/ZpeV1fU581HRp8ycOVinI6pVuQftCH1/6tTYoCALY1SIUs45IfrKyvo///mQ +kx6uyHVHTqc49JUA2na1Ar2zUXHOQZJweXnTO+/kAhj7nvmoMG5c9I08rlpABw70T0oKBVCc4xV+ +JNM//nHk3LkGwdw6fVz7txc2YoyxrVu3lpaWImecs4fbOACsXftdc7OVEOlGwgh6DJwDAImNDdTi +omcghhMTYwFg2glNCGltbX3jjRzoLNhWizSEUHl5+datW51G307AGwFU/amqqur48eOSJHm9EyQJ +V1Vd/fDDEwCG/jLxc84BkNEoAXRD8HpoCgDAZNJdP5PEIjBs2lRQXt4kFoEXFi9J0vHjxysrK8GD +PurTCvj+++9jYmJiY2O9CHQxFz766ERjYxMh0s1OO/AEIoDH4VBUDN4g2GyK20zihEhW69UPPsgD +z4tACIOYmJiYmBgRkd8pdEEAsXssKioaOnQoeBAj4pokYYeDbtpUAKDrD+eiOmwAoCIKE3ywBHgd +OwKAqqqrAC68XvBh/ebN37e3y5KEPWOGA0BycnJRURFowgOve0uX/bBarYqiCAJ4gI44hm++KS0q +qkVI31/TX2AHAPLza26kCTU5oKGhraTkCgBxGRHngLHu/PlLWVkl0FmwiRaGDx8uy3JTU1Onv3at +hgYEBKxevTo2NhY8y3TRvU8/PQ1ARZbnTcaytw4DSPv3lzHGvMxN39qB3NyLDQ3NGEvubYjYrU8/ +PeOpBRVXMTExq1evDgwM7PQ2bwRQce2Siu4OkoStVntW1vn+5T8AwBhHSHfqVPWBAxfAq5biCdSg +MQDYvPl7pwrE3V8EoP/669LGxnZP+qgAQojJZPLkG/BIAHXiMK/bWTWO6tixqsrKKwjp+rv2hBgk +FWqi6Ex3nU6UMknCBQW1//73GQADpZ1MKc4BY6murik3txKgI4PBS8ue3ANdywDkBPDo/AIA2Lev +FEDpNPSlbwExxhEyff756W3bTksSVhSP4RpuA7mWmgAAzz2XJcs2LxGJgtL79p33gjoXBLpDFwRo +bGwsLi7W1gXopAmMACAn56K7sOonEGUbpJUrPz93rkGnI7JMVX+Wx2ec2JdlJkn4j3888OWXZwgx +ednQcM4ByHffXVSR4OEeYIz98MMPjY2N3SCAQHphYeG2bdu8+h0BY9TY2H7mzCUA7+o/BwBJwuKD +8Q1F3HsFYVWWLl+23nXXxoqKZkED1UnrptJ0/KsojFKu15O///3Y73+/F2NTp8zn+gelwsLLly61 +CiO2xw4htHXr1sLCQnBj6dhz0wAADQ0N4eHhXpawuF5aeqW+vsVrKnOHl0pRWsSHMYcz1vWm0IAx +hrHh7NlLU6a8n51dIXwyAsXOND+uutFlmQonEsbouee+XrlyB8Z6sey9vINzQAg3NbWWlDQAeHMP +IIQiIyMvXboE18cVgpcMGTHrm5qagoKCwHMqj2iqqOgygEyI5FkjRgA0JMT/oYemMMbNZik7u+Lw +4dKbKbQ7aFBV1Txjxvqnnpry/PO3RUT4u3gyEOpYxAihb74pW7MmKz+/lBATpeCLFw9jRKlcVHR5 +ypRY7wMJCQnpdCvQBQFqampGjRrllQAcAM6fvwLAvOTxYIwYYxER/m++OU+WqU5H/vzn7MOHfyDE +IIzGN48GCOk452+/vf/DD/MXLhy+cGHK2LER4eH+BgNhjLe0OMrKmg4evLBly+mjR0sBgBA/Sn2N +GxNDPn/+CnheAeK62WwWDjIXNHZBgGnTpkVFRUFX4ebl5U2+ONc45yIwRKcjvZh54R1FnDPOESF+ +Vqt948bcjRuP6HTmsDA/k0lijDc12RsbW0SQIcZGABBJHD5uZYTtr7y8CTy4SVS8DR8+XPASn1iQ +2sqUKVPUnAsPdwIA1Na2+DhfCMGS1FHWrk8IAKJjlFIATIiZc5BlWl3d6JzjCIBIkr8QBt0NHhDR +QLW1LeDZ9C2iZuPi4uLj413Q65EAmjypTqrruOAUABobbW4Wq1sN1KhCBIAQujZwkSmlva27LTc2 +2gDAwxS9LoPapRwXdOkPgK58GkL/bWlx9GuAfzeQ5RyaWu/gWnC5Om7fmxMsqLXVIaLYfbv/OvDG +grR830vrjHFZ7gPvu8hX6ZhBIkyhM6q73MY830Mo5ZxTkQ/sXBmYENJVRTJXbMkyY4x7spZ5R6a3 +fUBLS8uWLVvq6+vBqzlFNQfdzG2wCM6hYg9BaZsT+7yz2xTnbe2aeobqDYKjUkVp4dxuNOojI4Ni +YkIiIgJNJj3nsqK0cE67lRPp3RAkfrpy5cqWLVuam5tdEOUtU16W5ZMnT6alpYWFhXnxhWGMhOHX +R5NLDwAhxLmSmDhw6dIxisIaG9vffvuou5EAIcS5nJoac999IxWFVVdffe+945p7OIDI226LjBzw +4INjfvrTxKSk0MBAA8ZI5AqUlFzZu/f8Bx/k1dZewdjkm2OVq3GPngiAEGptbT1x4oQIKtQi0xsB +JEkym83ecSra0uvJTfUBYIwoVZKSQl54YRoAlJc3/f3vx9yttOK21NTw55+/DQAKCmrfe++YBoMI +IWDM9sQT6X/961x/f9cAJ4vFEBUVMH16/G9/O3X58s+2by/A2OidBsJwrdcTX5Q6s9ks/Oq+pqmK +ux0Oh1cCdHS9D5wwKsZFioTnLl2z7WgvY4w4t/2f/zNt3bq7jUZJWEnb2uTy8qZz5xpqaqxCkDoc +1GIxbNt23223JTDmS342t1gMahKcJ7DZbACg07nW6/C2AvR6vUhE7Wq0KDTUBNC9ALQegLrKnUmK +ncO11S1h7UXG5Li4ga+8MotzTgi6etX+4ovf7thRePlyG6XcYCCDBwc//fRPHntsvMNB9Xry7LO3 +HTpUKp72/C4AYCEhRuiq8Ep7eztCSK/Xd4MAGOPHHntM1PL0nH8KABAdbfEgFW8VEEabO+5I9Pc3 +tLXJZrPu/vs/3bPnBMZ+jImodKWwsOrxxz9ubZVXr04DgPHjowIC/K1WG0Letzg8OtqiosIdBOqS +kpIef/xx99CeLvwB4eHhQgx42oWJ9e6s6dLfaO4KxoyJBACzWXfgQNmePWckKciZ44gAMCEGAOMn +n5wUN1ssBn9/PYA3didsQaIOjXcsmUymiIgI9xsk762L8nVqRpj78+JKSkooAOmrKgM9AcY6nPWt +rQ4AyM4uBxD7gA59X5hFAXBbm+K7QUIUAkpJGQDXMwltipxKg04R6G0jxjVlNzyB2AkPHTqAEEM/ +BoN2CZxzAN2nn5749NPjAICQjhADAEeoo2QQ54xzBaAlPn6okyRdj4UxBmBwEuAa6kGjC6hGuk43 +Yt6iDcUKsFqtfn5+nuISRVNxcUFxcUGlpZcRkm5VixAC4BgbCUGEYIdDobTdyV4wgC4gwBgVFTB9 ++k9efHG6ry0i4JzGxAQPHhwMzrmoTSRV+YdLQrX2YhcEqK+vX7du3YoVK8LDwz3xOEqZwSCNHRtR +WlqLsa6v7Mw9Ac5BURRZtpnNAWPHJo0eHT506IDBg4NiYizh4f4DBpj1euKJV7iD2HaMGRMhSj6p +GawIIVGhua2tbefOnQ888IBIquCaepLqsujCHxAYGMg5r62tDQ8PBw9iQEz5GTPit28/0d8Y9oZ8 +hDDnsr+/Yc2a2cuXj42OtrjkPAuk1NW1DhhgliRfeCkC4NOnx6tI4M6ikQcPHszOzo6MjLRarcXF +xXFxcRaLRSS3MsbKysqioqLE8RHehDDn3Gg0hoWFlZeXjx492jOlOABMnz4Yof7MCegCVQhxLkdF +WfbsWTpq1EBhvUEItbfLVVXWysqrZWWNZ8827N9fTik7cuQx8MG0RSkD0M+cORg6WLHgchgApkyZ +Eh8fn5WVxRj7/PPPbTabxWKJiopKTEwMDAz8+OOPn3zySXEgiDcCCGIOGjSouLgYPAgl9YyUUaPC +x42LyMu7eMP17W4UtPsvFUSm0IYN944aNdBmU4xG6fDhin/841hOzsXKyquybAdQMAbG6MiR8T7y +H8Yco0ZFjh0bKf510gA45xaLJSgoqLq6OiIiYuTIkefPn7948eKFCxf279/f0NCQkpISGRkJLn6J +zpArVMyU9vZ2tR5Kp3dSyiUJ3XNPSl5eGUJGgJu7DrwkmwLwyEg/l6uEIErtkycPmTcvyeGgRqP0 +t79995vf7EKIca5T62ASgh0Ouyj02hWIIgjyXXcNxRiJkihOSndwaUrpnDlzBMYSEhKGDBkixHJj +Y6PZbAY199UL9gVPTEpKSk5O9u6cEZczMob/z/8cuHkZ8S6ntbj/DsABsJiSLmMBoGlpMQCg15Pq +auvLL2cBSJKkUxQm3DLCNwDABUftCkSahnHx4hHunXGWLcCHDh3Ky8tDCA0aNGjq1KkiwCc0NFSV +85zzLjxiWsekp4Q/5KzNOXJk+OzZgwEcvgQoIoQAsBqn5eXj3CJdA6NRMplc3B8dWbQDBwbOnDmk +09GEh/uLb+XlV6xWGWNJRGupN0gSAXAMGxaqGbtHCzyAfcaM+HHjotQCNi5427VrV2ZmZnJycmJi +Yk5OjsPhOHnypOpcUbUgn6xa2mM/PBn9Bd9/9NEJaje8E4BzGaBFUVrVUC1PH84V56JmAKAoLDzc +f9y4CACbXt9R+EGSCCEYoPU3v7ltwACzqCbtAlZrh1k3IiJAr8ecc0lSH0eSRByOlvDw0Fdeud05 +duHkwm7hNuI7f/TR8eAWgC12r3V1dceOHVuxYsX8+fMTEhLi4uIGDRqUm5u7bds2uD5+ouvSxej6 +2kyeQDDBBQuGjRoVfepUDcZ6T6JYrI/x4wc98sjtAQEGr1l/YDJJu3efLS6uA5AqKpplmYrH//Sn +eXPm1FitzSK0i3PKOaxcOXvNmnS1sI8WKQD4++9rAcDhoEOGhDz2WNq77+5jTM8YEtoj5zBpUuLG +jfeKoiqEYEIwxgqAnXOjtmAlQpgxx9ChkYsWjQC38A6BpbKystDQUBEGcezYsYSEBAC4995733nn +ncrKypiYGLXUQBcEUGNSDh482NzcfPfdd3dapAA5yyHqdHjVqsmPProNIYO7KBaF6MUsnjVryJw5 +CV62PMLxK0m4vr61uPiiJPn98EPd4cMVM2YMttuVSZOi8/OfWrs2Ny+vRlFYQkLwL34xZt68RADY +uLHgrruSQ0PN6pZQxPLv23e+pKQhMTFUlunatT/9yU+it207U1fXoteThISQBQtS7rwzyWCQGhvb +jUbJaEQGg/SrX6W/8UZua6ujudnmHAvHGFOqPP30ZOFUEDWxtKgAAD8/v6tXrzocDs55ZWXlrFmz +AMBisRiNRhf/iq95wnq9/rvvvrNarWpghadF8NBDY1JTB1HaiStD6KyEYEKQpyqCngBjBMDWrNnb +0uIwGCRZpoMHB61dOz87+5EjRx7bvHnRHXckAMBf/5rzyiv7goONoIlY5hwwJm1tbatXfymyORnj +Dz00eteuJUeOPJ6dvfzDDxcuXJhiMEj5+TXp6RvKyhoRQna7smpVWlXVMw8/PAbARggSyg+l9pSU +qGXLxrlMf62eMmzYMKPRuHXr1ry8vIEDB0ZHRwPA6dOnKaXiu08uSe1948aNy8rKOnny5G233ebJ +LCoWgV5P/vCHmYsXb3KZzgCorU0+dOiC78YixlhgoLG2tgUAKwrD2HD8+IVZsz745z8XpqaGq3HO +oj/Nze0vv3zgzTe/iY+PPHSowmzWnTp1SdsUxsbMzNNz5360bt09Q4YEO+cQF1HTly+3vv320ddf +P9Ta2rxhw4m//W2uWoxAOFydwQ3AOX3xxZkmk+v0V3l1W1ub2Wx+5JFHNm7cKPhPTk5OTU1Nbm5u +RkaGwWDQchGf4gkFF9q9e/fJkyefe+457dmCbljukEJ33bUxM/MMIWZnpJ/qrunBeQgEAKsBDYzZ +JUmaPj1xxoy4uLggnY5cvtyan1+7e/cP9fUNGJsZY863IAA1XxyphVSMRuOcOUnp6bExMRaEUG2t +9ejR6qysksbGKxibADBjjgULRt5zT4rJJFVVWf/1r/yiolqEJIQQY+1z5qR89dVS7cFsKkIF9r/4 +4osFCxbodDpZlk+dOnXq1Kn6+nqz2Zyeni7OI9VObp8IIO6ur6/funXrkiVLhCbrKVZXBBsXFdVP +nPiP1lbFibsOGvTAaaNWkxT/OQ9BsQOoQZxC2OjV8Gz1LW7hPeJxUT6ROTmw+rhOhOUihDi3qSH1 +AHonq+BGI8rNXTF6dIRaDVQb+EYIaWxsfOutt1asWBEREUEpdT8IE67Hgk8pSuJLaGjok08+6QX7 +HS1ipChs2LCwV16ZA2BzMQyIXU+3Pi7dYYxxDoQYJcmfEDMhJvEFIaI66zXPos4eR86nTNc/TtXH +CTGpjSMkidgTgPY//GHW6NERatF3AfX19QL7lNLg4OCwsDCRGAwaxb2trU1dKNpJ373kKRfC+MaI +ThPi52RE/6HACSGUtt1+e0pW1jXmI5Bgs9lef/31gICABQsWDBo0CCH0zTffHDlyJCUlpbGx0Waz +ORyOpqamMWPGLFy40L3OW/fKVoLGeOuJBiLaUj2BdPLkdRUVTRjr+7tAdM+xL0rQR0YG5OauiI0N +FEPT8pPa2tq9e/eeOXNm6NChCxcuBIC33norPDw8MDDQZDL5+fkZDIbU1NROmUf3YtmcWZy0tbU1 +ICDAMw2u1e07ePDCnDkbZFn1Cv1n0aDj9BiEWFbWstmzh7gXylLnYmVl5e7du0tLS8ePH19RUbFg +wYLk5GRtbdtO0dW9mnGilYKCgrffflsEunRKvw5nm4QVhU2bFrdhwyIAu6hZeMvGrXQ6XBHKyLn9 +/ffvnT17iKi+6C5UBURHR69YsWLFihX19fXV1dUHDhxoaWkRKoOQLp1O1m4fZ4sQCgkJOXz4cFNT +0/Dhw9UW3TNDOOeEYEWhY8dG+vub9+49TYj+epXmVgYOgCQJUdr6xz/euWpVmkjs6TQHpr29/bPP +PtuxY0dRUdGkSZOmTZsWExNTVFSUlZVlt9tjY2NFPFanWUbdI4DQeXU6XVhY2K5duxISEgRf8xCa +isQ5RpTy9PRYQvTffHNGkv4jaNCBfUVpfeGFef/93zO0ey4XwwNj7P33329sbExPT9fr9YmJiQI/ +aWlpFoslPz9/xIgRJpMJPOjg3ZYB4NRwPv7448rKymeffRa8pvAh5ylVkoT/9Kfs5577nBAjY7jv +y8n5PkqEMMac0vaXX57/hz9M91SCXjipjh07lpWVtWbNGrWcoSzLe/bsSU9PDw4OppS6HMbuAt07 +yE3b0J133nnlirfsQO39hICi0N/9Lj0kxLRixQ7OMSG6W1I35RgTzmVK6TvvLF65cqIn7KuGkKqq +qoiICL1eL8syxlhUNTlx4oSiKPfee2+X7+v5ESYWi2Xw4MEuEqlTd42TBliW6eOPj//yy0eCg42U +tkuScKrcImJZJPITxtoDAgyff7505cqJskxdsK8OkznPlIuKiqqoqGhtbRWRz4qi6HS66dOni6TU +Ls9w7DYBtL1Rjy1xiezw9IgkYVmmc+cmHD/+1MSJgxWlhRDo6flcvYx9jDEhoCgtY8bEHj/+5F13 +JQudx9MACSFiso8dO9ZsNn/44YeiUqu48/Lly2qCu/cXd1sLguvLMoovly5dUhTFZDJ5OstE02+s +KCwkxLRs2Vi7nWRnn+dcIUTv9Oj2PUfqyBdjzME5Xb165iefLB440F/oPNrxav2INpvt8OHDR48e +tVqt0dHRI0eOzM7OPnjwoF6vlyQpNzf38OHD9913X1BQkJcM347GbySpSDWUbtiwwWq1Pv300ypt +vItlcWCLOI9lxYrdp0+XI2TEWHKu674hA3dGSimc21JSYtetu+v6s9w6hgiaEAWEUGNj4/r16yml +AwcOLCsrE5bnkJCQL7/8sqCgQJZlPz+/u+++e8SIEVor6U0hgIrQq1evvvHGG3FxcUuXLgXPSpH2 +EVU1stuVd9459uqr+5uaGvuKDNeh3mIJfP756atWpQkPl/ASg5PBqtNfDeh8//33CSHLly8HgLa2 +to8//ri0tHTVqlXh4eF2u729vT0gIEA1gnYZ5dgTFnQdARFijBmNxmHDhu3Zs+fixYujR4/2/mIt +OxJG3alTY5ctGwugP3WqzmazAiCMJe8FYHqGdwDkFKoK5+1+fuaVK9O3bFk8b16SKJWrMn2xshlj +Fy9erK2t9fPz0+v1CKGmpqY9e/YsWrQoKCiIUmowGMaNG1dcXHzmzJlJkyYRQoxGI3Kecuc9lkfA +jZ4nrHY0PDx8+fLl3377rcPhMBgM4HUdqNNKnISgKCwszO8vf7n9179Oe++9vPXr86qr6wEAQC8E +XbdOse3sdcI9KU4HdQBARMSARx8dt2LFhOhoC2PcRdcUgyopKdm5c6fVahWCbfHixampqeJXNW1L +WPx/+tOfrl+/vq6uLjw8XCj+XmoL9DIBtNSOj49ftmyZOgzBSbyXOVBrjgosRET4v/TSjDVrpmRm +nvvoo5P795e1tVkBAEAHIKk4UvPcPaFbcA6V0XGuUKoAcJMpYNq05IcfHn333UNFlqTgOcLCIxoU +6M7Pz//kk09mzJiRnp5OCMnMzBTFZgIDA+Pi4r766qvhw4cTQhRFAYCgoCBCiN1uB429wUffU68d +6KyuXK28cr/i4XEQfFk9XlkMoLraundvyZ49JTk5FysrmwDEKWDCQyk+1zXpNHIw50ds9PRRUUFT +pgyaNy9x7tzEmJiOoGj1CGn3GOnGxsa//OUv99xzT1pamjYmU8yn+vr6N998MyEh4cEHH9TpdAih +L7/88uTJk7/97W99n/i9TACVDNfaRSgvLy8iIiI6OrrL7bg7ISnlCF07q6u9Xf7hh4a8vOrvv68r +LKyvrLx66VKr1eqQZVlzJh4CwDqd5O+vHzjQLybGMmxYWGpq+PjxUcOGDTCZdFoFzNP5aoKlZGdn +Hzhw4He/+506lxFCLS0ttbW1JpMpOjq6srLygw8+UBRlxIgRjY2NFy9efOSRR4YMGeLLIeIu0Jtn +yrsYab///vtt27YtW7YsJSVFXQq+tAAA6lmaooSM0SiNGRMxenQ4dIh93txsa262NzfbbDZFVKrQ +6bDRKAUGGi0WQ1CQ0WVqi7P7xKmFWut8px0wGAytra1NTU2hoaGKopSXlx85cqS4uNhms1FKp0yZ +snjx4meeeSY3N/f8+fMhISH33nvvwIEDuQ8ZXZ0MuRdXgArq8L744ouvvvrqjjvumD17ttejNzy1 +I8JAROHBDtYv+IYXh6jTRX7tLFRN8lAXJdWdC679jTfeYIwlJiaWl5c3NDRERUVNmDBhyJAhZWVl +27dv/8UvfjF27NgunS39QwAt98cYnzlzZvPmzUuWLBk1apSWn/asu2pvPVVkVaN3tP92t32EUHV1 +dWZmZnNzc0JCwsSJE0U0lfhp3bp1gYGBS5YsURRF3eX2gPvfLAK406ClpcVgMOh0Og361KolXWvK +fQlaa4/LF+HVkiTp7bffjo6OzsjIELLtBvvfwyPNvYM6u4Uyqk2yFIYUdffgyX7Xl6BqONq9K3cm +1MmyzJ1nF0qSdOjQocrKysmTJ4NTON/g7OlNIawFtVtaHU5c+eijjzDGGRkZAwYM8FE43yTQmnVB +M+XVBVpXV/fBBx/Mnj07NTX16tWr+/bty8vLe+CBByIjIz2dpNZtRPXZ7FOXc2lp6RdffFFRUTF2 +7NhZs2aJBNjr+tQj8dDdzqjTXFWRtdtGZ2CHsmvXrtzcXJPJpChKWFhYRkZGbGyslwOsuwt9vfxV +Mpw9e3bHjh1JSUmLFi1y2eyoJtxep4SLyFH/LS8vz8zMHD16dHp6urtuc+nSpbq6uuDg4KioKME5 +u9xa3ooEUMejVmJUFEVRFJEuK8Zjs9lUY1ZH/9yQ1bP3goa0Ku7sdntOTk5+fn59fX1CQsIdd9wR +FxenfbX7svDdyuYj3CwZ4A7qNk0MQARTqmfNAYDNZlu7dq3FYpkwYUJSUpI4ckKrh2hnnIvBw9O7 +tPeD2ykuIm8rMTHxoYceEjsp7SMuEkIVxb27KPtHA3HX9gTDPXv27MmTJ8+fP2+1WtPS0jIyMnqw +uXdRIgU0NzdXVlYWFhaOHz8+ISFBZXoqu+uyQupNgr5bAVpwd2oCgCRJw4YNGz58uKIo586dcxED +R44cqampGTRoUGBgoMViCQ4OFhsLLaIZY4qiUEpFjSN1J7hjxw5ZlgkhgYGBqampLj1RVaA+EP6d +oKJ/dXABWg4LTkah5d0iSe3YsWMOh8Nms8myvHLlyujoaDGR29vb169f39LSIqwI4eHhK1euBKdh +ubq6uqioaMiQIZGRkULegJvZqh93grcEAQRop7N2q6xlVoyx1tZWq9U6YMAAbSDU8ePHEULiANOg +oKDY2FithHCRFv0y0z3BLUQAT6C6d7TaIfiAR5c9bZcBA/0C/wEEEKDtZ6duHy1a3Wtk37LwH0OA +/1fhphjjfgTf4f8C4VLHz/5KLxoAAAA8dEVYdGNvbW1lbnQAIEltYWdlIGdlbmVyYXRlZCBieSBH +TlUgR2hvc3RzY3JpcHQgKGRldmljZT1wbm1yYXcpCvqLFvMAAAAASUVORK5CYII= diff --git a/gem/input.bin b/gem/input.bin new file mode 100644 index 0000000000000000000000000000000000000000..d24a95495b55894b96aec1b01d0b7c02cc43f168 GIT binary patch literal 11732 zcmW++1ymGm7oH`T4vD3t6_iHlmKN!jUJ*q)M0$ml4r%F-?(Rkw1f;uDI;HcU@1L`A z&hG3xbMD^v-Y0Ibx~c*JE;TLy00c^kvYOyK;=d;p4SZEGI!^%rPAw%_Y3(nw``+#@ z+H#YZC52O;q6g)Bl}USLraK2Qg7$Fz@nAnRBwR5Zr4vbf)|SIW2J?Idh4}}=@OJR~ zcy=JN4uB*Ju0|~DuW}aRuPic(GQG-Br7ezyI}@F|`~1_jk<vF(q$U3K0YJ;ImxnqIVrJD)*0_au!r(hC8CxFA^2o+Lf5kb64 z>*Yn$i0Rh3b7WNR<^N^eVjo458Ow};G)uUWX2%9(ymGEf6aj91t+u_Hs=Ug|Xw4l5 zAs3N_E+R=AzC;)twpOH9_IG_c}6sn**$rhYO2AIsRqMas}{!22RRMUY#g>}f0?5`f$9U(DgE z=VgXql9O04ZEkM*-X8aKbaasX|5!tXhlYinTGkel)y(ZDa2ZFlus?gIObmlJTMeaM zUtcT5JOOWrDqP-FC_2O&kb>S{4c#V~%$gc|;{Xsv00V$H0EF$pJK%-Ohk;LJe;PK^ z$dsvMdhrOZV*tZ=rhX?mIXNSv6c(k`r$rO9WWqwU$>w$cDeEf95Z3$eFJ*3j(Y$qdwfl`bQ^=sXA%1DG(9vj>cBLpN-5eSL4ffuDoJX7yJv7|$wwj%Q5T1wc#o zT9b&0l~f+A(q^ihH*r$Aq%_EYaq@G~-Y!@S%i8uBrHl;P=qQ#( zAMa0X`ERuU5Jm3efR#ou8vMlUfz=PkhtF& zy|AXR`-vxzeUnf66P}rg^7Av5S9tqNWH{m=cg|0n10ELnSp0gYs4PvwoBBnH;jny> z!g-=bhh>f9;3HB}-4esIf9VhN!sGxjS$Y@YjE#b2G?7WAILl-Q1mvFWMxrCsbBqq_ z-I=wmCUagV)Y>nZn3zbo9n2SK<>5BC?dsc$EQCTQa%v|C+c(EGAJ%KUFE`XW7U;1%C zZf!LMA|)-&33S04oQamc63Z5>4J5uUC?Mf#Ie3Hifwi!Ikd2Qon)eAyiEi6z&dWjR zX@Ex_X$C|PpWjz!#Hz25e+y~J&j?Y&;`?Ju$!*f&C?8IYW)>Hx*YW53;wOw@i*#a5 zefd!DZb|S?XV1bTq+2W4SR=SXe|({^#t>7TglHwv}Dd5UH}KPh#xa z0WJL>OBvE%M@AsLyc97?fy5LW;CHqvC z!pzLCh=G)5@@8wHXYypu-6i=S?r;CmOWYJ+_C_feP2fsFf-V`dyYvqW3>YQZEx~|1 zd%oLtS4)hzyunsUB5N^|?(@TZwYKW_3-@QNJCpzL5`;lQLb3SA!EVMBf|n4nw&ve% zi+dhHT{ue}NhezC{_n44e|-33aYIW{<17={46i(l*&x^RJhs?0{b53nRp2cifHiEc zg5>S*zTBY07^6Ii;l*V@=kf2bKi@<4Jf;DQb+n0EGwgu;n-b|@-?K!~3sV@4oh%gH zK}p7H@Rm>59YKt2Q36U>cl+X=>y;WQsi^ElZx>yY=2$QX%*}0t)8H+BVXmvMCj|g} zBr$@Jek>fF5ejH1L-qhLjx8Rpvt2}y=l{lvyn#Q~#PUJ8Pv(wRK7Fz-hMt){#Rm|) z76TF=HTR;JpU>L{304z1?0hpy?PX+S#KFO7H8cGX7{ZjzNPoSyyN1Ojh7^V6itQ4U+12{z zhre^r*2t?xk57xI+sD>r59YZYW2Le?h8(q9vJ_Vr!2@6q2qo8;9XV% zlsFj}8YU$t7m>c=saI`i)14;uo12R>y*~*(J-s+N>4P4>QdDE#f3$}VScGXQlSD(0 zx!Ll6@WSsNsqNX>x(4Me)1tBAzE;6^KkhaFY(bWfi9*4E0h;2Rx^wMxwYi`usmI{ zTUqs-1xKq7QyKlLzISJbEI4@Y*(M>IUSqj(Zi~Y5@yV=8Hof9e(#Ra*um+B|=^oa9Kb0+HS}f5? ziW@=DG7}RMb8^7)$Q8$;RQ^+yHDt0NoY!MDc*ysx$QRu#>?}6qkGZ57J)<5vNe&rY z95u>6v}aVi$8Ro8YT`O5oyYue)AriuZda77TeX0I@jHu5P`QJP7gRc0mUuO`)&jq* zt#xa`?T~Ex@J~KeCwgzLj+=+ap%aNy7}fJ=i83vGQuoSAa_)K~0W+E`gRM9jZ6E6^ zIzz>NmNt?*=qo&o7iHl&@0iSDE>|&_ChpV|al=XBztud=t4J#0Rlj<*c|j+pk89?3 zK+w$w12D~yKMq?xr|BPrK3yL1$eAzx^!HE%)EJ>Ap{YDOo0<`aQ5;SN zumrOy@BRw*ud0m4!lde!0;GxxnUL=iYwMmvzs?jpn_w7F2#`naToRB-*^YSH1bI|( zREZwWU!F~Ui(X&aobCZ|H~WTsCGIy8tg^H59S*BPdiLi+O}?z`j*e2x48%GCTpxIB z4Nn$Zh-mQXR>YTI2;xNN$EtIa`tedogq7Nsw&I%G0v-2vH=jOz5`}I}G_qF*DbU{) zo0doN{+%a*eVA_ew^H(!^6Aq+&Awls^=>j_`}tTg!1V9c%F~rN=_OO1gF=98HtpzJ z!pFDf+oN@V<4>nL0WWr3Q^DyyM`*_xu3mW9`2 zs*^)F9c8T^W@{+sJH895n4ei3*hCVo4(1^oS}UU@`eQy&X%RXSPcHwjHq+(Hae9BX zth->sAD7!)cPl7O=M|v2+Hts~`1rr8e_gQCbrFpR zswqMmT3Y;8gS3Yic&;V6xf{VxCD5f(+@_FDKM}lW4$W78Q`dSFglV;rVV(*|XZuKK zM_9#_Npf;pn(W7>@(xErU{p)(&R$Ngip8A!ob)(k&c3aswpM_fTdjK$OoeaGn}ctD z@R%>Rf3>)7TFRJJfGlt4x#{V=B+lAw<`!)1ythn#`DyE9V~yQXgzi9-v~gGpItN|? zj{yfAXETi0*w}cj%%^6~^2b3t41~2bl0MDLGRDp03Y@*aCkwLJX1xM;54U+%lt~vW zH^zPMrryh_#GcnALKuHFi1Ryd-(LOB;%|M5U+^I(_BH8X?{uZJ6@>9gCK-tzyY0t&oyW*RT_?i($Nm??qi~d>u9i>w5xm`JEPNZu~I`R zY{FADWn4`4lr?f6mNChD$MyLJtd4mRZ=;(!N&$%A6EyTviB8~OsN?(TjyS@Jej zeo3{R2BLjeP*}KgdAt_Q;@Z9@ z8S{&Y$7WVr-DHu4;wvQux6+6&pZ4jcE)fo?{5y_78Vw8cnj2pmr~+-OBN1) z#5np#RrCmh3DL8nu8qIQFl`eur?QGv)ZLvRlITSr3YCKT|M>5Kkwh)AyGR2So*d7f zQH!{+eIaIEO=2+*^tYSU1~PVuHnT)*fD9(wM_%O^U+6^95Fp?LxSCCl%pA}S7UuU;D%unrrP2U7$P(R1}XX=!QYwS6uLz{0>NHfa$N z5TFq2cNu9>lN2YAl8fJbgQ~0}L|44INZ>^^54>5L{W?D%N&`1pIL0`?f{j{DIe2ZYhc5?xQ-$*cPfNsv=2D7x)vpM6EAY%hvm#Tn1w z1*V&?Jo9jWEtq0tJY4UNqEMgJuJZwzpx^IK)@hCu0oPTYvN?m75j)crg?)X`q1)F@ z=SUa}xpmf-id(8`ET2**CT0!DLa6}soKzL|K?uB{w3J=2jx>YWzvFd(+B~{(Kd_E* zv~`OHOxKl>No~J4&9R5@qDc6>@2|FP=Tu*l>XJpSP}`w5#3up3kaz-XzW_H$u;1v- zdFq9q2qi}2D@u$HHZ~kwT$7WSTiG~a0K?PGtfumvr^J>t*>TS$CEZHF?p~>);~U>& zl`@@R`9$e5(pT&VY$Z@$_nBdbK}fILlCgHw^2%egFfaj$!o$NC7!Xn(=H@H4wsXzb zbP)LX^t8|40aoB}M-m%Q>Rk0dCXk!=#5C85=Q6Ebbe%$lguItVpHSM(9d)@aVhhtO zor-CDxSKxoZKH&1^oUlLLdf*Jj`>dAA-wpijvIm@AxL~z*xBW)M=zF7T3bP$Gb zyF4Gpgjic!%ZF2M!~wLxV0s%`d-M9SSr`mXLUM24Dy$Y?psH|xySdjD=*#enAq*uL zi3Qyj+5|hnLl@CMN-kQkLxQ-OWM$z_D_Y^5CpNLvUfPm zqgN8X_qbn7AghftHWY+>lrKI@BR+!YQBF=;Z{_dC#+z25DWOd!9@#wRmLKjbbaE;D zgCvYTx<%e=sQGZ3$Ss$@IS`aif4k6njofNfW1_z%0<-Mb^UQKbu2K>9S3PDD|S2d9eNHc=`$9EBJkbHp%dC z+0dau#BM415l4Q_1Y_2;chiH&5z4RHYw7iFn4`e~`e9SA-u4e^CY4P7!lrqY*wQPu zjTEgYqCF$3AH<_Na(sF=zxm){o|W3Z5|(?3y)a-~4js(2 zAd>!={OG2+YL0Bvc0b7@V28l(r>5M;m3g}tJIu`f78Wv0OlWVOh;LSARXeCQ#XZ_y zAZGDtblT_xR|6@IG4TecmP!0Z%u}`8oSbjpzPTTNGY>&fuABFD%yD1zA9)>hnc6$yPd&NM~?VNv2s{eEeuLy^R3C#kF4YJp6&>4`nnP zIREu%+xKqQ$k%rYcpBPGOis?@?Qv`GE9!c6GE{5N4I-~ptWJlLsYj-z!5 z1tCpzgn@c!E-o!ZDLl_mav{h~F5{~G58UuDp}M>D2Y%ay#-?z2C4Hs2+4Yl?T<1+{ zYwKc}?;^D07Q8ldpOKQc8_9*LO$?MzSa7~ePI>vxagU^(ZJb`2 zDmvnL?I#-AZHX?8%wnC8n8<8aRwo_CPIPqiW8YiHi{Uh`TL@SZW$?euehWT3DBd1j z`fz}Y3Jb;nstnwgrDoE^tytK56W4+O9!4x+?P+=nnc!OvEMH%7gy83=Hqu#y;cgs> zD!D;H&g-v{eAoMo=r`EpLce3i609oCw4G|)6r-c z8irPsmhBCQLk6Wa$P8)||3Kh9Pr@J5Nw{nwI{d*6%K_F`bgUm|AZ6C8_n-b829gA2 zi2|x(D5FMZLrID4=3pw3*bzdpa5>2%dZ%)$lb#p`>lH35DIp*t!X~niQn{kyU#+v3 z99e>$2Y4ZQHY?lO%>N|K^e04yN7UA@i{WLDPt*{?%;H&0zp$e%kLC3gDJ~CYMPU;? z9vB>q2n(w=ECFS8P!pyIm1C*nL-qCbWo2dkIwn~JSDXLvBH-J%xP$~yPMzh?5du`w zC19EN12|h~I#5S01v!KBJp&QzaVhf_X=qJdzmCpiUtf`>Ww_Olz}}LnD!ZuDI`2_O zwH!P8@KA~{Ohmt8*$D>Zsw9%q)2GM9b;E9M{|(s+BzIc`hlD7rsNmz{-(IdorhAR9509!2|8UM_-;hW*}k6cE~^2xVns%WrHH zVPdja?~U3VN^kpey!s7~^89dVX?Xa1bTlay6%LnA@Zk67+5@rY=bvjHE9bds_OaqD zIIAg}m{7^cBa)j4n^}_4j(Qa(6N-=w%KI@-i4q05f3IZ7|2(a0^S(%4+LH-#EY;dI zBlV*rY+^f|B@bePo*26kbi;z9*;JL?96l;mXLn2Oo4-tFhM zf+$93Ymq&f=j#*%+A$UOab=SN9FJE?4pJTCIom;vzOTRk6_kMb#fP2o0;cw-FJ5TJ z{Y&}BC1zpRlbwf@Trd73?DXz(Z^j=&+ls-)gapc|^ENit=9!Gqe`@e08qL$w8C0WV zV-2PVXOE2_18+j@H#YQ&b*bP=vY!eB6-glu_%sxSR80zaVhC?k*rnrI);O8~*Oxhv zJimYc9z^RPXHZp*=vonSKgr%P(x_obFE*ToONvq5VJ`Wej^J1eHa|i*Q)S3$7*42j zs?iUUZ)Uv*GT1o8=6&bup+K_9lE$TUG?WpRaVFT-VA~E<e%GuCfhlIdI_Jb-O=u?>sggFDV`2Yynt|Oa_=2&0+feZmVR;M@fx=HN$)-c zf>mbVYsRP4a1p7_KWoicWq$DX z3};4#QiKC_M}%KucKr5ijpW^LwX8Z@Q7yfxtf?3z@;fG;=0P+6Z?o?p!U&iD z{XrJX|Fp<7r|nqY?o-jvhMB*#cs($!Lb1EkcPrY&FDt6^0YFl+4J1(_w1k81mX;gE z230`2MFlKep7J52%)Qg2<-X~#waT!>+U#4N+|lqWxTY4i#%%EOS6jtk0Kexw^GgHZ z810kAGjpS>JTMl6T(ISq7>i1Z-b67gJf3TIAE9$&0oqL;lK%BQzwz@A&j{B4OUv^F zG&G9zeAz37sn&?ZUwBNFvMNM~rKPsqb`gOt-46>M#jC5A+uJmKebgi}pPMSJbqsYT z_=zONu-fIJq6=?QM*41Obn&8cS;-t@=M-;ZNu*n#e~u~%c!WW z#RQ(?c1=6nUVbyElDOQIq|D6?C~_RklKk^$pS#U#`Hx^*aAc&IOMa)#WU7d((i|BI zH83#dyy;VIw;=v107G<>m{MabfxE8t?tEm*RC0WFw%NQZxb4oi)G$m+$SAdgpk3Je zxI6Jl%rn~b50kTO&Kg#nC9# zb67IK1CPMOlV5aJ3;E5WqhkPCZns%khDa79F?`?oZ?@Ojgyw#S%`+Ly^R~;?P)t0E zEf*1kcr`F2VD-Dc_NbakNlW7zWS&s9ONTNXl$Mn(HM;Ibv%W??*=5(&!=RxgpHNG= zjGWZ%4sIf(K5hT_Q#Xd}L6}Io0zF?kMP_hNV({4q4)lowtN?5r3x?UBz!Gsj5 zD_}eWJf0RU%QN@=G3NDfK^hWh(_G3!Kib%M?UvN(7VCq~w=}z}B=k{fkDnU5^6Kjk zAGTuDB(^bc=r}F1*+5CMT+bvC-OQO6Kgd|EPJ(N}Jj{_031j`8PR!5v?k-kP+rax1;eNA zZYe2wW6UJggv(wf?s>D4c-o)!0eQ?CgIz1A5W#w}vypnFI_(-J-{H zF)=Y7p5b?VS65e5_yObNnZy*H!Z+=aj?(?+Uh-#^rjjb6=ofN>+A1qL4{*vq9w^OD-I;& zbxS^PF&bTz+X$_ak>uarBvaIxcQFA?`37J5Q6(-SMkIZ`4R?1JhpFP8LHVs)T-unj z3JPWVV9y942g5osF#-CDA3lC0dFKC}D^+#Uj@~Mi7#9ae*z3|kOKa?CrE7v>f&Ufg zbDGIz!h7VeZ;~$##NPznd&K?K#Uezo;AqTV_ed@_SnDJy?rp!o&TVPAs~VD+tAHzL zXpCel#pHrF_2`k7wsve>oMqh{91fQg)6FxGUtmTIySs`Q>+4UK8aILP0mJkkaZ<=H zVfomT(^Gw!()jRc$9-e%fO z3NbUh{;>b|m4q^q2bD5){v8sLHN14kCC>7z+M=6qke9LXt)}1x?9rg5 z^0w$92Pm~4q`_+D682oj7I6YhRKl)m;$VUSm5v4Q>1KH+fpisT7JsO8ae2N!99 zmRooXmVW&9T4dzINxuSE+GA^9M>`bGGg%n0oIFC!qNCxb`?k7l^aWR{7?+n3#t09^ zhK7U`=I4K~wIz=l3d!1XX#}fuX!bbQki(t;q`E~TlG8DG@8~p$#oPd7iBD)H@5e!t zg*@jQ@z(a0QA?P27%yW68z&s~>#^khy0IH8UTV)6fWv4}3EIGuHUhqvD}h;>MfLwq zHu|monl32a-s1V~_Va~sgEKFhWZm!h+(r6j$Lx#QIKVjA%;-0zzOzc-G-8xJJl#4M zSJ>&Lgb#EG8@G7;eVWekSZLUEOKkSo`YuQyc^}L*g~-P>h9x5-Bg_gBAi$USa+G0G zmcYU;D0l&W3jzUC&{9aiUy4B4vlJ-4jJ2CC@35|sxH}ztX4@QU>1Y-z6lvKVvXG~i z!2Ir)zEkOLD<6LLI%{wRL) z`}gnMZMT&f8B+0#4k<^SljyvxoQng! z#`B$`o8%4&Ocd&Xg!OY%OG}G51B28{zt2<~(~l@z=pZB(VN~HL^R9sXnX1jz?oe>X;QZc# zQ=Ifr328yj1YrZo=?6;7jPWaRaCAQ7BXB9RG` zXLd?++7yphXb(?&TKxHin3&hq$p)yZlyt4|!0?w{>GH>vQ;;B{mv0VWv*Y+ z9aP&|!8x3juE0k!WO5J$IR7LQv|xuF-qNA4q*X?@Ra|OR((Kf>y5dOeWgu>1fS=Jg z+vsNhJ58KbSeWwp^JL%`yIJQec8RH%+b^7WHWh46Pc<~8wQ}*31i2j#=70V85s~rX z4Epf`wv9re+HN?uFWc_zc+ugps zclu?E3J`}sH7m!)&CSik#3Ulp*uP&d%E-O}H5M%@YB9cF2@Gg%-Z^Y5d(Kf@R^05d ztywg&^WD=IZq|A5@f(uY3@(JY5@`=aI6EYs)y}g(Hn@Uj8pL&DD@DyJ4dY`jw%EH)dJC1{b>8XxbgO>&T<48c2Z=p(ouFJv|T)aQ+3_$jiVa%Cc#WqZGFDIy|bu(y}Eav$qvsf+nf zi@!+IH@?C*m1F^At{2O{eWnsJtc7MaX(c#+{J2eN>ZPHf@n1{~s@?}l`?pP>OS&x*dCX-rHKT=`WQqbmSfzw^bd5Dt zU--|lb1~UJ=jA=l417!~%D&IcMJhwy-O|K%qk!%>b&k;mmfAfq+C%A*_BDoMqoaI$ zd>-WuZW>IOF9Zekbag2xC?e=3B^Vi{Ej^w!?N-X{yzy&&3o&$XvqnR(D1keY1|0Ut zVguzgXA*RU2wJdGQoZ<~Zf2IzZGl5bNI`?gnMDN;$x>IA3uktHS`Y6bG>FGx1k(vT zlS^DfCqshxJ~boD*VO@HNQkE@pSiKXq_jU>0VfRXdSCUsvKds_x3)g;M$OI5O_iB0 zjgB%EL&44jPGMo>nKytD1~CPg@ljDxGK+}hnL>Iuzd8&E#)rJB&qc+Sx?vTQle$F{ zB4+J?EyFlyv69HF0%I8&8Pn7HB}j)TiaWkB@eWQ|KrN%ut$LR65}}YFZkqr>ze9U~ zU=U~QTjkl&a~dvudbd=0ME?r$ptq6>Tl2wKT6sWQ(d-$zSLUV$r>w4cb*_ovF(q$U3K0YJ;ImxnqIVrJD)*0_au!r(hC8CxFA^2o+Lf5kb64 z>*Yn$i0Rh3b7WNR<^N^eVjo458Ow};G)uUWX2%9(ymGEf6aj91t+u_Hs=Ug|Xw4l5 zAs3N_E+R=AzC;)twpOH9_IG_c}6sn**$rhYO2AIsRqMas}{!22RRMUY#g>}f0?5`f$9U(DgE z=VgXql9O04ZEkM*-X8aKbaasX|5!tXhlYinTGkel)y(ZDa2ZFlus?gIObmlJTMeaM zUtcT5JOOWrDqP-FC_2O&kb>S{4c#V~%$gc|;{Xsv00V$H0EF$pJK%-Ohk;LJe;PK^ z$dsvMdhrOZV*tZ=rhX?mIXNSv6c(k`r$rO9WWqwU$>w$cDeEf95Z3$eFJ*3j(Y$qdwfl`bQ^=sXA%1DG(9vj>cBLpN-5eSL4ffuDoJX7yJv7|$wwj%Q5T1wc#o zT9b&0l~f+A(q^ihH*r$Aq%_EYaq@G~-Y!@S%i8uBrHl;P=qQ#( zAMa0X`ERuU5Jm3efR#ou8vMlUfz=PkhtF& zy|AXR`-vxzeUnf66P}rg^7Av5S9tqNWH{m=cg|0n10ELnSp0gYs4PvwoBBnH;jny> z!g-=bhh>f9;3HB}-4esIf9VhN!sGxjS$Y@YjE#b2G?7WAILl-Q1mvFWMxrCsbBqq_ z-I=wmCUagV)Y>nZn3zbo9n2SK<>5BC?dsc$EQCTQa%v|C+c(EGAJ%KUFE`XW7U;1%C zZf!LMA|)-&33S04oQamc63Z5>4J5uUC?Mf#Ie3Hifwi!Ikd2Qon)eAyiEi6z&dWjR zX@Ex_X$C|PpWjz!#Hz25e+y~J&j?Y&;`?Ju$!*f&C?8IYW)>Hx*YW53;wOw@i*#a5 zefd!DZb|S?XV1bTq+2W4SR=SXe|({^#t>7TglHwv}Dd5UH}KPh#xa z0WJL>OBvE%M@AsLyc97?fy5LW;CHqvC z!pzLCh=G)5@@8wHXYypu-6i=S?r;CmOWYJ+_C_feP2fsFf-V`dyYvqW3>YQZEx~|1 zd%oLtS4)hzyunsUB5N^|?(@TZwYKW_3-@QNJCpzL5`;lQLb3SA!EVMBf|n4nw&ve% zi+dhHT{ue}NhezC{_n44e|-33aYIW{<17={46i(l*&x^RJhs?0{b53nRp2cifHiEc zg5>S*zTBY07^6Ii;l*V@=kf2bKi@<4Jf;DQb+n0EGwgu;n-b|@-?K!~3sV@4oh%gH zK}p7H@Rm>59YKt2Q36U>cl+X=>y;WQsi^ElZx>yY=2$QX%*}0t)8H+BVXmvMCj|g} zBr$@Jek>fF5ejH1L-qhLjx8Rpvt2}y=l{lvyn#Q~#PUJ8Pv(wRK7Fz-hMt){#Rm|) z76TF=HTR;JpU>L{304z1?0hpy?PX+S#KFO7H8cGX7{ZjzNPoSyyN1Ojh7^V6itQ4U+12{z zhre^r*2t?xk57xI+sD>r59YZYW2Le?h8(q9vJ_Vr!2@6q2qo8;9XV% zlsFj}8YU$t7m>c=saI`i)14;uo12R>y*~*(J-s+N>4P4>QdDE#f3$}VScGXQlSD(0 zx!Ll6@WSsNsqNX>x(4Me)1tBAzE;6^KkhaFY(bWfi9*4E0h;2Rx^wMxwYi`usmI{ zTUqs-1xKq7QyKlLzISJbEI4@Y*(M>IUSqj(Zi~Y5@yV=8Hof9e(#Ra*um+B|=^oa9Kb0+HS}f5? ziW@=DG7}RMb8^7)$Q8$;RQ^+yHDt0NoY!MDc*ysx$QRu#>?}6qkGZ57J)<5vNe&rY z95u>6v}aVi$8Ro8YT`O5oyYue)AriuZda77TeX0I@jHu5P`QJP7gRc0mUuO`)&jq* zt#xa`?T~Ex@J~KeCwgzLj+=+ap%aNy7}fJ=i83vGQuoSAa_)K~0W+E`gRM9jZ6E6^ zIzz>NmNt?*=qo&o7iHl&@0iSDE>|&_ChpV|al=XBztud=t4J#0Rlj<*c|j+pk89?3 zK+w$w12D~yKMq?xr|BPrK3yL1$eAzx^!HE%)EJ>Ap{YDOo0<`aQ5;SN zumrOy@BRw*ud0m4!lde!0;GxxnUL=iYwMmvzs?jpn_w7F2#`naToRB-*^YSH1bI|( zREZwWU!F~Ui(X&aobCZ|H~WTsCGIy8tg^H59S*BPdiLi+O}?z`j*e2x48%GCTpxIB z4Nn$Zh-mQXR>YTI2;xNN$EtIa`tedogq7Nsw&I%G0v-2vH=jOz5`}I}G_qF*DbU{) zo0doN{+%a*eVA_ew^H(!^6Aq+&Awls^=>j_`}tTg!1V9c%F~rN=_OO1gF=98HtpzJ z!pFDf+oN@V<4>nL0WWr3Q^DyyM`*_xu3mW9`2 zs*^)F9c8T^W@{+sJH895n4ei3*hCVo4(1^oS}UU@`eQy&X%RXSPcHwjHq+(Hae9BX zth->sAD7!)cPl7O=M|v2+Hts~`1rr8e_gQCbrFpR zswqMmT3Y;8gS3Yic&;V6xf{VxCD5f(+@_FDKM}lW4$W78Q`dSFglV;rVV(*|XZuKK zM_9#_Npf;pn(W7>@(xErU{p)(&R$Ngip8A!ob)(k&c3aswpM_fTdjK$OoeaGn}ctD z@R%>Rf3>)7TFRJJfGlt4x#{V=B+lAw<`!)1ythn#`DyE9V~yQXgzi9-v~gGpItN|? zj{yfAXETi0*w}cj%%^6~^2b3t41~2bl0MDLGRDp03Y@*aCkwLJX1xM;54U+%lt~vW zH^zPMrryh_#GcnALKuHFi1Ryd-(LOB;%|M5U+^I(_BH8X?{uZJ6@>9gCK-tzyY0t&oyW*RT_?i($Nm??qi~d>u9i>w5xm`JEPNZu~I`R zY{FADWn4`4lr?f6mNChD$MyLJtd4mRZ=;(!N&$%A6EyTviB8~OsN?(TjyS@Jej zeo3{R2BLjeP*}KgdAt_Q;@Z9@ z8S{&Y$7WVr-DHu4;wvQux6+6&pZ4jcE)fo?{5y_78Vw8cnj2pmr~+-OBN1) z#5np#RrCmh3DL8nu8qIQFl`eur?QGv)ZLvRlITSr3YCKT|M>5Kkwh)AyGR2So*d7f zQH!{+eIaIEO=2+*^tYSU1~PVuHnT)*fD9(wM_%O^U+6^95Fp?LxSCCl%pA}S7UuU;D%unrrP2U7$P(R1}XX=!QYwS6uLz{0>NHfa$N z5TFq2cNu9>lN2YAl8fJbgQ~0}L|44INZ>^^54>5L{W?D%N&`1pIL0`?f{j{DIe2ZYhc5?xQ-$*cPfNsv=2D7x)vpM6EAY%hvm#Tn1w z1*V&?Jo9jWEtq0tJY4UNqEMgJuJZwzpx^IK)@hCu0oPTYvN?m75j)crg?)X`q1)F@ z=SUa}xpmf-id(8`ET2**CT0!DLa6}soKzL|K?uB{w3J=2jx>YWzvFd(+B~{(Kd_E* zv~`OHOxKl>No~J4&9R5@qDc6>@2|FP=Tu*l>XJpSP}`w5#3up3kaz-XzW_H$u;1v- zdFq9q2qi}2D@u$HHZ~kwT$7WSTiG~a0K?PGtfumvr^J>t*>TS$CEZHF?p~>);~U>& zl`@@R`9$e5(pT&VY$Z@$_nBdbK}fILlCgHw^2%egFfaj$!o$NC7!Xn(=H@H4wsXzb zbP)LX^t8|40aoB}M-m%Q>Rk0dCXk!=#5C85=Q6Ebbe%$lguItVpHSM(9d)@aVhhtO zor-CDxSKxoZKH&1^oUlLLdf*Jj`>dAA-wpijvIm@AxL~z*xBW)M=zF7T3bP$Gb zyF4Gpgjic!%ZF2M!~wLxV0s%`d-M9SSr`mXLUM24Dy$Y?psH|xySdjD=*#enAq*uL zi3Qyj+5|hnLl@CMN-kQkLxQ-OWM$z_D_Y^5CpNLvUfPm zqgN8X_qbn7AghftHWY+>lrKI@BR+!YQBF=;Z{_dC#+z25DWOd!9@#wRmLKjbbaE;D zgCvYTx<%e=sQGZ3$Ss$@IS`aif4k6njofNfW1_z%0<-Mb^UQKbu2K>9S3PDD|S2d9eNHc=`$9EBJkbHp%dC z+0dau#BM415l4Q_1Y_2;chiH&5z4RHYw7iFn4`e~`e9SA-u4e^CY4P7!lrqY*wQPu zjTEgYqCF$3AH<_Na(sF=zxm){o|W3Z5|(?3y)a-~4js(2 zAd>!={OG2+YL0Bvc0b7@V28l(r>5M;m3g}tJIu`f78Wv0OlWVOh;LSARXeCQ#XZ_y zAZGDtblT_xR|6@IG4TecmP!0Z%u}`8oSbjpzPTTNGY>&fuABFD%yD1zA9)>hnc6$yPd&NM~?VNv2s{eEeuLy^R3C#kF4YJp6&>4`nnP zIREu%+xKqQ$k%rYcpBPGOis?@?Qv`GE9!c6GE{5N4I-~ptWJlLsYj-z!5 z1tCpzgn@c!E-o!ZDLl_mav{h~F5{~G58UuDp}M>D2Y%ay#-?z2C4Hs2+4Yl?T<1+{ zYwKc}?;^D07Q8ldpOKQc8_9*LO$?MzSa7~ePI>vxagU^(ZJb`2 zDmvnL?I#-AZHX?8%wnC8n8<8aRwo_CPIPqiW8YiHi{Uh`TL@SZW$?euehWT3DBd1j z`fz}Y3Jb;nstnwgrDoE^tytK56W4+O9!4x+?P+=nnc!OvEMH%7gy83=Hqu#y;cgs> zD!D;H&g-v{eAoMo=r`EpLce3i609oCw4G|)6r-c z8irPsmhBCQLk6Wa$P8)||3Kh9Pr@J5Nw{nwI{d*6%K_F`bgUm|AZ6C8_n-b829gA2 zi2|x(D5FMZLrID4=3pw3*bzdpa5>2%dZ%)$lb#p`>lH35DIp*t!X~niQn{kyU#+v3 z99e>$2Y4ZQHY?lO%>N|K^e04yN7UA@i{WLDPt*{?%;H&0zp$e%kLC3gDJ~CYMPU;? z9vB>q2n(w=ECFS8P!pyIm1C*nL-qCbWo2dkIwn~JSDXLvBH-J%xP$~yPMzh?5du`w zC19EN12|h~I#5S01v!KBJp&QzaVhf_X=qJdzmCpiUtf`>Ww_Olz}}LnD!ZuDI`2_O zwH!P8@KA~{Ohmt8*$D>Zsw9%q)2GM9b;E9M{|(s+BzIc`hlD7rsNmz{-(IdorhAR9509!2|8UM_-;hW*}k6cE~^2xVns%WrHH zVPdja?~U3VN^kpey!s7~^89dVX?Xa1bTlay6%LnA@Zk67+5@rY=bvjHE9bds_OaqD zIIAg}m{7^cBa)j4n^}_4j(Qa(6N-=w%KI@-i4q05f3IZ7|2(a0^S(%4+LH-#EY;dI zBlV*rY+^f|B@bePo*26kbi;z9*;JL?96l;mXLn2Oo4-tFhM zf+$93Ymq&f=j#*%+A$UOab=SN9FJE?4pJTCIom;vzOTRk6_kMb#fP2o0;cw-FJ5TJ z{Y&}BC1zpRlbwf@Trd73?DXz(Z^j=&+ls-)gapc|^ENit=9!Gqe`@e08qL$w8C0WV zV-2PVXOE2_18+j@H#YQ&b*bP=vY!eB6-glu_%sxSR80zaVhC?k*rnrI);O8~*Oxhv zJimYc9z^RPXHZp*=vonSKgr%P(x_obFE*ToONvq5VJ`Wej^J1eHa|i*Q)S3$7*42j zs?iUUZ)Uv*GT1o8=6&bup+K_9lE$TUG?WpRaVFT-VA~E<e%GuCfhlIdI_Jb-O=u?>sggFDV`2Yynt|Oa_=2&0+feZmVR;M@fx=HN$)-c zf>mbVYsRP4a1p7_KWoicWq$DX z3};4#QiKC_M}%KucKr5ijpW^LwX8Z@Q7yfxtf?3z@;fG;=0P+6Z?o?p!U&iD z{XrJX|Fp<7r|nqY?o-jvhMB*#cs($!Lb1EkcPrY&FDt6^0YFl+4J1(_w1k81mX;gE z230`2MFlKep7J52%)Qg2<-X~#waT!>+U#4N+|lqWxTY4i#%%EOS6jtk0Kexw^GgHZ z810kAGjpS>JTMl6T(ISq7>i1Z-b67gJf3TIAE9$&0oqL;lK%BQzwz@A&j{B4OUv^F zG&G9zeAz37sn&?ZUwBNFvMNM~rKPsqb`gOt-46>M#jC5A+uJmKebgi}pPMSJbqsYT z_=zONu-fIJq6=?QM*41Obn&8cS;-t@=M-;ZNu*n#e~u~%c!WW z#RQ(?c1=6nUVbyElDOQIq|D6?C~_RklKk^$pS#U#`Hx^*aAc&IOMa)#WU7d((i|BI zH83#dyy;VIw;=v107G<>m{MabfxE8t?tEm*RC0WFw%NQZxb4oi)G$m+$SAdgpk3Je zxI6Jl%rn~b50kTO&Kg#nC9# zb67IK1CPMOlV5aJ3;E5WqhkPCZns%khDa79F?`?oZ?@Ojgyw#S%`+Ly^R~;?P)t0E zEf*1kcr`F2VD-Dc_NbakNlW7zWS&s9ONTNXl$Mn(HM;Ibv%W??*=5(&!=RxgpHNG= zjGWZ%4sIf(K5hT_Q#Xd}L6}Io0zF?kMP_hNV({4q4)lowtN?5r3x?UBz!Gsj5 zD_}eWJf0RU%QN@=G3NDfK^hWh(_G3!Kib%M?UvN(7VCq~w=}z}B=k{fkDnU5^6Kjk zAGTuDB(^bc=r}F1*+5CMT+bvC-OQO6Kgd|EPJ(N}Jj{_031j`8PR!5v?k-kP+rax1;eNA zZYe2wW6UJggv(wf?s>D4c-o)!0eQ?CgIz1A5W#w}vypnFI_(-J-{H zF)=Y7p5b?VS65e5_yObNnZy*H!Z+=aj?(?+Uh-#^rjjb6=ofN>+A1qL4{*vq9w^OD-I;& zbxS^PF&bTz+X$_ak>uarBvaIxcQFA?`37J5Q6(-SMkIZ`4R?1JhpFP8LHVs)T-unj z3JPWVV9y942g5osF#-CDA3lC0dFKC}D^+#Uj@~Mi7#9ae*z3|kOKa?CrE7v>f&Ufg zbDGIz!h7VeZ;~$##NPznd&K?K#Uezo;AqTV_ed@_SnDJy?rp!o&TVPAs~VD+tAHzL zXpCel#pHrF_2`k7wsve>oMqh{91fQg)6FxGUtmTIySs`Q>+4UK8aILP0mJkkaZ<=H zVfomT(^Gw!()jRc$9-e%fO z3NbUh{;>b|m4q^q2bD5){v8sLHN14kCC>7z+M=6qke9LXt)}1x?9rg5 z^0w$92Pm~4q`_+D682oj7I6YhRKl)m;$VUSm5v4Q>1KH+fpisT7JsO8ae2N!99 zmRooXmVW&9T4dzINxuSE+GA^9M>`bGGg%n0oIFC!qNCxb`?k7l^aWR{7?+n3#t09^ zhK7U`=I4K~wIz=l3d!1XX#}fuX!bbQki(t;q`E~TlG8DG@8~p$#oPd7iBD)H@5e!t zg*@jQ@z(a0QA?P27%yW68z&s~>#^khy0IH8UTV)6fWv4}3EIGuHUhqvD}h;>MfLwq zHu|monl32a-s1V~_Va~sgEKFhWZm!h+(r6j$Lx#QIKVjA%;-0zzOzc-G-8xJJl#4M zSJ>&Lgb#EG8@G7;eVWekSZLUEOKkSo`YuQyc^}L*g~-P>h9x5-Bg_gBAi$USa+G0G zmcYU;D0l&W3jzUC&{9aiUy4B4vlJ-4jJ2CC@35|sxH}ztX4@QU>1Y-z6lvKVvXG~i z!2Ir)zEkOLD<6LLI%{wRL) z`}gnMZMT&f8B+0#4k<^SljyvxoQng! z#`B$`o8%4&Ocd&Xg!OY%OG}G51B28{zt2<~(~l@z=pZB(VN~HL^R9sXnX1jz?oe>X;QZc# zQ=Ifr328yj1YrZo=?6;7jPWaRaCAQ7BXB9RG` zXLd?++7yphXb(?&TKxHin3&hq$p)yZlyt4|!0?w{>GH>vQ;;B{mv0VWv*Y+ z9aP&|!8x3juE0k!WO5J$IR7LQv|xuF-qNA4q*X?@Ra|OR((Kf>y5dOeWgu>1fS=Jg z+vsNhJ58KbSeWwp^JL%`yIJQec8RH%+b^7WHWh46Pc<~8wQ}*31i2j#=70V85s~rX z4Epf`wv9re+HN?uFWc_zc+ugps zclu?E3J`}sH7m!)&CSik#3Ulp*uP&d%E-O}H5M%@YB9cF2@Gg%-Z^Y5d(Kf@R^05d ztywg&^WD=IZq|A5@f(uY3@(JY5@`=aI6EYs)y}g(Hn@Uj8pL&DD@DyJ4dY`jw%EH)dJC1{b>8XxbgO>&T<48c2Z=p(ouFJv|T)aQ+3_$jiVa%Cc#WqZGFDIy|bu(y}Eav$qvsf+nf zi@!+IH@?C*m1F^At{2O{eWnsJtc7MaX(c#+{J2eN>ZPHf@n1{~s@?}l`?pP>OS&x*dCX-rHKT=`WQqbmSfzw^bd5Dt zU--|lb1~UJ=jA=l417!~%D&IcMJhwy-O|K%qk!%>b&k;mmfAfq+C%A*_BDoMqoaI$ zd>-WuZW>IOF9Zekbag2xC?e=3B^Vi{Ej^w!?N-X{yzy&&3o&$XvqnR(D1keY1|0Ut zVguzgXA*RU2wJdGQoZ<~Zf2IzZGl5bNI`?gnMDN;$x>IA3uktHS`Y6bG>FGx1k(vT zlS^DfCqshxJ~boD*VO@HNQkE@pSiKXq_jU>0VfRXdSCUsvKds_x3)g;M$OI5O_iB0 zjgB%EL&44jPGMo>nKytD1~CPg@ljDxGK+}hnL>Iuzd8&E#)rJB&qc+Sx?vTQle$F{ zB4+J?EyFlyv69HF0%I8&8Pn7HB}j)TiaWkB@eWQ|KrN%ut$LR65}}YFZkqr>ze9U~ zU=U~QTjkl&a~dvudbd=0ME?r$ptq6>Tl2wKT6sWQ(d-$zSLUV$r>w4cb*_o t1crlf.txt") +crlf = readfile("t1crlf.txt") +assert(crlf == string.gsub(lf, "\010", "\013\010"), "broken") + +gt = readfile("t2gt.qp") +os.remove("t2.qp") +os.execute("lua t2.lua < t2.txt > t2.qp") +t2 = readfile("t2.qp") +assert(gt == t2, "broken") + +os.remove("t1crlf.txt") +os.execute("lua t3.lua < t1lf.txt > t1crlf.txt") +crlf = readfile("t1crlf.txt") +assert(crlf == string.gsub(lf, "\010", "\013\010"), "broken") + +t = readfile("test.lua") +os.execute("lua t4.lua < test.lua > t") +t2 = readfile("t") +assert(t == t2, "broken") + +os.remove("output.b64") +gt = readfile("gt.b64") +os.execute("lua t5.lua") +t5 = readfile("output.b64") +assert(gt == t5, "failed") + +print("1 2 5 6 10 passed") +print("2 3 4 5 6 10 passed") +print("2 5 6 7 8 10 passed") +print("5 9 passed") +print("5 6 10 11 passed") + +os.remove("t") +os.remove("t2.qp") +os.remove("t1crlf.txt") +os.remove("t11.b64") +os.remove("output.b64")