From 2e723672e29e60559943f6120cd4f068a8514882 Mon Sep 17 00:00:00 2001 From: Tomuxs Date: Tue, 29 Apr 2025 01:59:15 +0200 Subject: [PATCH] Initial commit --- .editorconfig | 10 + .gitignore | 21 + README.md | 14 + config/Factorio/config.ini | 5 + config/Factorio/icon.png | Bin 0 -> 101670 bytes config/Generals/config.ini | 7 + config/Generals/icon.png | Bin 0 -> 292044 bytes config/Lethal Company/config.ini | 1 + config/Lethal Company/icon.png | Bin 0 -> 21346 bytes config/REPO/config.ini | 1 + config/REPO/icon.png | Bin 0 -> 99697 bytes config/ROUNDS/config.ini | 1 + config/ROUNDS/icon.png | Bin 0 -> 28227 bytes .../config.ini | 1 + .../Sins of a Solar Empire Rebellion/icon.png | Bin 0 -> 81881 bytes config/hoi4/config.ini | 1 + config/hoi4/icon.png | Bin 0 -> 5087 bytes config/meson.build | 12 + meson.build | 98 ++ prebuild.py | 117 ++ source/lua/lapi.c | 1087 +++++++++++++ source/lua/lapi.h | 16 + source/lua/lauxlib.c | 652 ++++++++ source/lua/lauxlib.h | 174 +++ source/lua/lbaselib.c | 653 ++++++++ source/lua/lcode.c | 831 ++++++++++ source/lua/lcode.h | 76 + source/lua/ldblib.c | 398 +++++ source/lua/ldebug.c | 638 ++++++++ source/lua/ldebug.h | 33 + source/lua/ldo.c | 519 +++++++ source/lua/ldo.h | 57 + source/lua/ldump.c | 164 ++ source/lua/lfunc.c | 174 +++ source/lua/lfunc.h | 34 + source/lua/lgc.c | 710 +++++++++ source/lua/lgc.h | 110 ++ source/lua/linit.c | 38 + source/lua/liolib.c | 556 +++++++ source/lua/llex.c | 463 ++++++ source/lua/llex.h | 81 + source/lua/llimits.h | 128 ++ source/lua/lmathlib.c | 263 ++++ source/lua/lmem.c | 86 ++ source/lua/lmem.h | 49 + source/lua/loadlib.c | 666 ++++++++ source/lua/lobject.c | 214 +++ source/lua/lobject.h | 381 +++++ source/lua/lopcodes.c | 102 ++ source/lua/lopcodes.h | 268 ++++ source/lua/loslib.c | 243 +++ source/lua/lparser.c | 1339 +++++++++++++++++ source/lua/lparser.h | 82 + source/lua/lstate.c | 214 +++ source/lua/lstate.h | 169 +++ source/lua/lstring.c | 111 ++ source/lua/lstring.h | 31 + source/lua/lstrlib.c | 871 +++++++++++ source/lua/ltable.c | 588 ++++++++ source/lua/ltable.h | 40 + source/lua/ltablib.c | 287 ++++ source/lua/ltm.c | 75 + source/lua/ltm.h | 54 + source/lua/lua.h | 388 +++++ source/lua/luaconf.h | 763 ++++++++++ source/lua/lualib.h | 53 + source/lua/lundump.c | 227 +++ source/lua/lundump.h | 36 + source/lua/lvm.c | 767 ++++++++++ source/lua/lvm.h | 36 + source/lua/lzio.c | 82 + source/lua/lzio.h | 67 + source/luad/LICENSE.txt | 25 + source/luad/all.d | 10 + source/luad/base.d | 224 +++ source/luad/c/all.d | 9 + source/luad/c/lauxlib.d | 250 +++ source/luad/c/lua.d | 559 +++++++ source/luad/c/luaconf.d | 780 ++++++++++ source/luad/c/lualib.d | 74 + source/luad/c/tostring.d | 26 + source/luad/conversions/arrays.d | 98 ++ source/luad/conversions/assocarrays.d | 63 + source/luad/conversions/classes.d | 288 ++++ source/luad/conversions/functions.d | 670 +++++++++ source/luad/conversions/structs.d | 137 ++ source/luad/conversions/variant.d | 127 ++ source/luad/dynamic.d | 171 +++ source/luad/error.d | 20 + source/luad/lfunction.d | 190 +++ source/luad/lmodule.d | 60 + source/luad/package.d | 3 + source/luad/stack.d | 638 ++++++++ source/luad/state.d | 581 +++++++ source/luad/table.d | 349 +++++ source/luad/testing.d | 27 + source/lunch/color.d | 97 ++ source/lunch/conf.d | 158 ++ source/lunch/http.d | 114 ++ source/lunch/launch.d | 86 ++ source/lunch/logger.d | 84 ++ source/lunch/main.d | 128 ++ source/lunch/ui.d | 1 + source/lunch/update.d | 419 ++++++ source/toml/LICENSE | 21 + source/toml/datetime.d | 74 + source/toml/package.d | 18 + source/toml/serialize.d | 294 ++++ source/toml/toml.d | 1143 ++++++++++++++ template.toml | 62 + 110 files changed, 24511 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config/Factorio/config.ini create mode 100644 config/Factorio/icon.png create mode 100644 config/Generals/config.ini create mode 100644 config/Generals/icon.png create mode 100644 config/Lethal Company/config.ini create mode 100644 config/Lethal Company/icon.png create mode 100644 config/REPO/config.ini create mode 100644 config/REPO/icon.png create mode 100644 config/ROUNDS/config.ini create mode 100644 config/ROUNDS/icon.png create mode 100644 config/Sins of a Solar Empire Rebellion/config.ini create mode 100644 config/Sins of a Solar Empire Rebellion/icon.png create mode 100644 config/hoi4/config.ini create mode 100644 config/hoi4/icon.png create mode 100644 config/meson.build create mode 100644 meson.build create mode 100644 prebuild.py create mode 100644 source/lua/lapi.c create mode 100644 source/lua/lapi.h create mode 100644 source/lua/lauxlib.c create mode 100644 source/lua/lauxlib.h create mode 100644 source/lua/lbaselib.c create mode 100644 source/lua/lcode.c create mode 100644 source/lua/lcode.h create mode 100644 source/lua/ldblib.c create mode 100644 source/lua/ldebug.c create mode 100644 source/lua/ldebug.h create mode 100644 source/lua/ldo.c create mode 100644 source/lua/ldo.h create mode 100644 source/lua/ldump.c create mode 100644 source/lua/lfunc.c create mode 100644 source/lua/lfunc.h create mode 100644 source/lua/lgc.c create mode 100644 source/lua/lgc.h create mode 100644 source/lua/linit.c create mode 100644 source/lua/liolib.c create mode 100644 source/lua/llex.c create mode 100644 source/lua/llex.h create mode 100644 source/lua/llimits.h create mode 100644 source/lua/lmathlib.c create mode 100644 source/lua/lmem.c create mode 100644 source/lua/lmem.h create mode 100644 source/lua/loadlib.c create mode 100644 source/lua/lobject.c create mode 100644 source/lua/lobject.h create mode 100644 source/lua/lopcodes.c create mode 100644 source/lua/lopcodes.h create mode 100644 source/lua/loslib.c create mode 100644 source/lua/lparser.c create mode 100644 source/lua/lparser.h create mode 100644 source/lua/lstate.c create mode 100644 source/lua/lstate.h create mode 100644 source/lua/lstring.c create mode 100644 source/lua/lstring.h create mode 100644 source/lua/lstrlib.c create mode 100644 source/lua/ltable.c create mode 100644 source/lua/ltable.h create mode 100644 source/lua/ltablib.c create mode 100644 source/lua/ltm.c create mode 100644 source/lua/ltm.h create mode 100644 source/lua/lua.h create mode 100644 source/lua/luaconf.h create mode 100644 source/lua/lualib.h create mode 100644 source/lua/lundump.c create mode 100644 source/lua/lundump.h create mode 100644 source/lua/lvm.c create mode 100644 source/lua/lvm.h create mode 100644 source/lua/lzio.c create mode 100644 source/lua/lzio.h create mode 100644 source/luad/LICENSE.txt create mode 100644 source/luad/all.d create mode 100644 source/luad/base.d create mode 100644 source/luad/c/all.d create mode 100644 source/luad/c/lauxlib.d create mode 100644 source/luad/c/lua.d create mode 100644 source/luad/c/luaconf.d create mode 100644 source/luad/c/lualib.d create mode 100644 source/luad/c/tostring.d create mode 100644 source/luad/conversions/arrays.d create mode 100644 source/luad/conversions/assocarrays.d create mode 100644 source/luad/conversions/classes.d create mode 100644 source/luad/conversions/functions.d create mode 100644 source/luad/conversions/structs.d create mode 100644 source/luad/conversions/variant.d create mode 100644 source/luad/dynamic.d create mode 100644 source/luad/error.d create mode 100644 source/luad/lfunction.d create mode 100644 source/luad/lmodule.d create mode 100644 source/luad/package.d create mode 100644 source/luad/stack.d create mode 100644 source/luad/state.d create mode 100644 source/luad/table.d create mode 100644 source/luad/testing.d create mode 100644 source/lunch/color.d create mode 100644 source/lunch/conf.d create mode 100644 source/lunch/http.d create mode 100644 source/lunch/launch.d create mode 100644 source/lunch/logger.d create mode 100644 source/lunch/main.d create mode 100644 source/lunch/ui.d create mode 100644 source/lunch/update.d create mode 100644 source/toml/LICENSE create mode 100644 source/toml/datetime.d create mode 100644 source/toml/package.d create mode 100644 source/toml/serialize.d create mode 100644 source/toml/toml.d create mode 100644 template.toml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..af92807 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# Top-most EditorConfig file +root = true + +# Use same style for all files +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e528f29 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Binaries +/lunch +*.exe +*.exe~ +*.so +*.dylib +*.dll + +# Ignore common editor/system specific metadata +.DS_Store +.idea/ +.vscode/ +*.iml +*.swp +.cache/ + +# DUB +.dub + +# Ignore testing script +/test diff --git a/README.md b/README.md new file mode 100644 index 0000000..f74e12f --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Lunch Games + +A modification of [lunch](https://arch.myddns.me/gitea/Tomuxs/lunch) that +compiles launchers for several games, hosted on arch. + +# Lunch + +A general purpose application launcher and updater. + +## Libraries used + +- https://www.lua.org/ +- https://github.com/JakobOvrum/LuaD +- https://github.com/dlang-community/toml diff --git a/config/Factorio/config.ini b/config/Factorio/config.ini new file mode 100644 index 0000000..ae131cb --- /dev/null +++ b/config/Factorio/config.ini @@ -0,0 +1,5 @@ +seed=http://arch.myddns.me/app/lunch/?factorio +exec=bin/x64/factorio.exe + +[exclude] +mods \ No newline at end of file diff --git a/config/Factorio/icon.png b/config/Factorio/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6ee4c33ba9e2a586b86164f5d1f6e32e2e279134 GIT binary patch literal 101670 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�$wDL2{{M%chHL_ zg=(3^nIj7+MMEK;SRC%2AQyBBvOs^YhgLRNe)0-|<6#IHqe7MA!#=a=oJ&;+Ro9sG zM#!&ffh4)c!rna!Qis+`DmyOX85_3l})c3Z!9x>$uFFfT|&p zm&*+MeLAf&PQA+)2N6ouK-3kkt~S|z=acNqCWl_c#>3~ixZ1+|^!R<**FdFi{diZ4nwxBd8K=@;Ko4i|euh5BO;QQBSxrcAGY zncYwQ4Q2lk5Oqo#*1J1D!=@RwYMmw{FU9T;DZ2w26`gvkiKkci)UHEy zazI7XnGWZiFC{e3Z}WG5bC=1TeJbR%i!$pAWe!rEPwqPCfkRD$R#~P}5E-}`)S;$i^b?hZR_WoDn$bFmozHt75x zo8QChAOBl?;-7w!%Wr?0q7oySWweUG@cM7yCKf;SGrvZBeTV1XdyQB(2>L_nB?Gfo z#t~(_VV|0svb5YLmlf>68JZ%{ZB-~&D#T$xDoA|w-YKQj=PXolXH(qD0#hrXHr;0^ zltC|IPc4M`ob^@_#VjBi1@x6AY&XKlbBex8wNm8HnZtY*pcN_@r3#Uvp%qH#nu@5Z zWJyZsyQFDKlq6(vj2{LFfGWvEQF1_@{^fH)baDn6-y#yr41R!L>0Ly2Q3k+0;l8 zs5L7@vX0}&6y=oj=htYgZ(^q+t`{?$SiE`tP1Y5Q)khwuH;riI4oaS26pPSW=JqV- z&TDTXk4{+t;6NY0C`c4clkQ5J`tkyCdx6sjM>zXObaavR?N#*kRsQ}Lc5(0S@nerx zNz#l-loDk*ulFxHK;HnbbB^@AS22mGl=7ysMu zT1fuxYEhC71~$cK-$C>7tLW=bpcSv--~M^dz3<(ed+smO-+7HU?>KB;{T`&u;$QsL z|B45neu?+L^E|DK+jv2YcXC3hUM8#7a88aXD>?Hh#q(T>TmNK}|P zA*$D>sYF!jO)M{F|8&C4i-;#v#3*1U7-T_+sVYoRx$a8bxpz!il_-_V*eFaVHo??m zFi+@(8B%8jNz<9R9*SG7 zO%qtC>6n!og=!Tif=pDg#v{b}fX%ICCXt95dPEuI#R^U;5?DU__YN=xf!6W@{gXat z5B3Rz94FH_igF6AE|M(c&Zp#A2BJt51Y~K3tn0{vKokW?vVtPXxQ<1fL?XHHF+WLc zAm>|1;@f~yD(mlgV&y|(8e=E|q#1&&A>=vH+yz-hE|?5YCxjU^7n<0UDS|38o;XO& z1~pS>*q;)QCusF5lj9zt=Q176s2ei5JHe2^_G9YKfQ9Wf_NM_`HI>4JhxzP5iayxK z2@@VXIOO4t2Gylyc6xJasYAK5gwbge$|nAJie!yhH3e)p;qYCUW*LWJ#^EI7d_}@k1!}s)k)5++We5V)4FM2Hb8x~0HStSNR`c(E|5oj7 zvpCy1v6Ex|GxE-J)p!2TIsKR3UGbhh*c~ISw7L3c|2&;{{BaWNE?@oRuOe$Xxp0Eo z-C+5#$Ej9FNNNZAce(fc$GQ8JuX5*BpVJ2?_|pNU%!ipxp;jbNbxx)Z>3qa`!$dW7 za!I4CWEh%^KOT@v8ohZ)yJ|Ag8-!+^V@ITv`E*JOv7{4)Ddzem`m>1DPLVu^+1O&% zpR&~`Qd;a{AD?0vI`+(_n8AKlW`AnaE*A-N5jRdyG@UrlK@br{ku;4dRw{^sh(Jyf zM<9x*nogXhv7W~tx8k(Vx0u9#NZ?yy?Sg#cLP7q2t}QnhosJ2^h`AjgNHS3-P?RB` z%t#~|$`y+3I&qQ_rI2MQJGTyLFSaqd zB#}JMD5VZ!vxDn}6vdc43aI1(i(9MojW*-sGYU=*Ra4Ol1r#zgO=D)c)J+AW)}X8A zEI#!R6Qzg|#;k8FU~aFH7EEHZ$dQwBbAQPBnu;vJ{ZUNcNs$DB)r!c!qlr0A2$~3G zDJ2LJlq8nc>gM)VQ~RSI*(kO**4wvU+MCV!Hul_VrS_vwcK^x`Zt4Gc(djj8(L}p= zo~`fw2#tzPI`5-i_yA(doN6ZUY}?9qQug< zOT&fOE2 zS$~M01cVt}SZ|^V#z3#pE8QYAE_(( z-8cK*UA_(d;HC19e&|B&CqA+)|H0XVJu$0R*!rFivGv>|^sSh|-XWcLKZ_7Yj9&O6 zwT8)K?|YWv?fZz{n92SbfqjR&pZ_fK+(XY}!s(QYPhKT$bqVJVVxAGYF6FXLtzO0~ zmdGj%3It?OfFKBDS%L&q z>kTALCyhd)C?X2{H`P4+@2!|Kz70rx8~7aLEmQU0e!2c5Mp-AzpxNyprwMA7Fr4~~ z=00MQGMzZYSxyv1%=`$;4(S~aSiiW&)>4Cdv&!nDm$0pXXm^*#pE!@XzKL&n_N(V0=sE_HGyu8$X_ z}*CfoujHMi6|3k8n)w8Ff$J~B!#!JUpQvzbf0&>?Gm+(W%_27 zyN6@kxlbmEv=o6<5}2nT%OZ-9)AMr53M`x8WzZ_X{?MZkSX?Tkn~KPXmRrgn&{TEf znZ-i#@TGR|_5E4GH^CpcSZaJ=yZZJIY!v^yx34$iVT)TtyCtCQ)FGi6HQ*-ALE7*LZO6{2`IWw zxl}?R$B$!VMMcOnWJN)gWPE!@=*$rXfjCYO1R>Om#veC|71y$?m~R6T-zEn0FsK!a zYae-b%aB|E;co)%L~X!%v4a(l88dtBuO%=tvYv=7O(D(Fs7%>h9fi?Hdor5x*(psJ!jrjm96nJ}xN=HPI~@>9=}Pxnwok?`IP{PBI>eDQfwwS?0< zVsWcWG&*HIa|vXH2X_x?NIBB>20OcFh|ZM4Qim*vP<0K76e*7>ni`#@4tc4@X@5*n zPG~N)kpWp#DYaU-eoVn1)9SQ1@gz=X0XKJh%+GqP>oKj8K|v8Y$coGo32QW_Xeb1^ zOi>akFE10sIYO54(kSEB-T+O4zU2}K67^DIEOsT_;)l_MO0)W z-zCekzp>w+e8RG5V@4U?nUfWo9leWODn>DZ%FX12?&*TmL%%!Phpqof>!bYdU^7&2X zQyX*xHy0TVJw`_ZmI@N9*Ead}!x6L5jMBs+o_Ul*pXb(0E}viG&Txnqc2 zb&b1|gj^J`Q-Lsobsc6Y1PR1BtXCj(19roJc;fM$75Tq#6aI@IKWFwfKeTmp7Awck z@6Z43-GlMx|KzrIw!Gab{Q5~SYy9ei_+yaqzvE-y{kYkzNyb0>+^z1T3+3;A$5!>j z{%qE6Vqd&uM%cN`jUyMoTBiNJXHX|T*36-Cd7Z_JYn%!SFMsM4uCz5O7aoNRAK>~w z`>)x%exGX}c#3-mQ!a}-%5cPupZpnSM}52$UK|BDwnO*)0{36LOEwuY^=%d$8{2kC z#x8oTPNu2I)e1L9A-QwL+s-xV=`98`o5pgL!C*pmJZ3Q+Qd(W&fuoTG4&Lwq8ksfhcXGy>98#*5m`vvMvkZUOqtQ;$3tNPX z>l`0lM~>&jPC`d;F_#yxMTIl1%>A7Kns4Lz3F&A;&oC*4If|j-S!06JF^2E+ht~@{ z`Oe3qhE~G{yC{R!!s8@cpaP{|8Ec-;GZqH+1xZ zrcOswr>5jZQ#VVCb#tj($u2b_d+GnWnN|wIP;!SZrsq-<5)OS4*VNg1+uJBDb=Z35 zGB5txi+Gm9$(=*G%PlTF{t)M$e1=*7fam}I|BrY4xqrasJDwvGbDEDl$q#?W_cH#K zpW|0P{S|agV)5ZioSeDb`r>OmT#8AWb-aVyEXxU$3}jiN)ooxT2K|{$O$;%_I*o8h zL9&^rEq10M(%Bwqa{PQtkc$=WJ~&`SwGl-bH;lP`>>|!abmf5I)MeH1@db@wW)s^U2X`OP z6n$#V25RPGI{__HvLs=9wT0Mhq9#6ZOrnPD z%|+RnFBKDa>uuHe;jM!B+`8(&cU$t_^;9|fz}2$wt`#MCcFjny7}G%~JLwssD2UTk zK#l{%N(ZmiC0X9YFE=60I2p`%{rNYz^6tmD`qB4u=l&7H+xy)4<=>=GDzg2qcQW0% z&1;|gmu#*ySiHQARA?bN1A2FNiGq~+a+@1g!tF1;!F!fWwl8mC&0Q9Bfm*$Sl!jDW zHArI2#U=72p{z^9g({*qCsvD0Q<{(60SeV^y;=RNJ7+h*?FnVqfUWxZqL*y|=_Czgm%gaIo+00|L< zgklHF5g-V%l~^GHLU4*4+q?F9y*oR*)9>7V&prK|x0k1v-}CDoO!)&TDA@AO-1&SE zWhhD_)nq=I(^E^5N)uZwX-Oq|vq`nrMX1)9O*|goc#y;hc8y%Oa9s}>$l{0~j>zJO zV6#RMMT}|Wm|QFWczcZpmFK@k7y+1md{e8EWkR}lE|N~C!5&f)OCGpLJ(VwjXj ztXCTp+s3X~tmh7C7}M$1`Gwba*|SAtQ{(v}LAP}3BwT&^oEim#ue`>(eAa` zloGzALgl@(aFyw7CNqBdt!?syH(166L(!*M(Wva-BTsXmGz|qm6OjN@6IrDq6+`AM zDp>d>yLF9840FFg%`;S~zz_;<0(d-2*pea$BNlGV@gimv<``*8krYH>N~%|pw}+_J z2J5K6@j?#YzRxfJmA}C2|I#ng9`E-=VSHWiV{h?zQOd447VAfh>_O7pUHX zT17|c>_Dx;fApVxhsVG5d(`GPeCyei7cVC$w#jt1VE*)&z5O1&uY4IX@G!|yTOBM_ zBr74=IGBwZqHaO#Q;LwKF^XZLX)2MRkVhesB4bu1w6=z82-O?bQkEsKaoH(aeE4u&17yM4U5Lz$IijV8I{ z5V;=idd1ztE^EmkyEtXr$jGZLC}2y^XzlNEu}nCBbxD{Dv>J61S)nWoIy#7zCV{9R z3xH;@k!{B3m%LstkQAN8!ey(fK&3{MX1Ga?EI=kJytM`&-o zNhOW3drj7gf#wFZ6a`Zf>8SAB$??;inl9o;IkpI1S+dRw8kWW+ED^+lT+~UT6x%ik z3xQg*#;Zt0C~{20K<#al2?e$(VYj>7SbfG(#`!2_f4_%)=QgFF(CfDeH63TMW|I^I zc7JRU;h^j=jSwcxA^SUh{=yWV^EWL?cE2INklTAk;Dm#EV3Al zNLLdo%?AE-f-OWW+>rHrhOG#+>K2kLl9+W)#|x}x2 zdOBr0TXCM~tk2HT(ikC5Xtf%gEkg3elASvTeA5xQes+THuerFG;f1jALr@KTQD%|k zwVpdN!s!Kc~67jhE#}S;DL|aMvEM?KW8z8uRg-ffDle*S^drp$V5SnN1g{-k956 z6HSs30vEl}=4QOWE+UFFWj&pe2NAFD)=36O#D-0~ZjfXG;l`z^D`a6p8YetEz9J3Q z#Bs#@Y>Kg%(7k`a=`v)K2`o#A%abcQa)B@$GU(Mg6AZ>T3vRV-G@&FzBt$@yB`Ug1 zl;k*Jj;)ILAr!j7I*94iD=5Qla=U_>X5@m1Aq&Wo#3T_pTSx46tBBn`m730LZ{4P5 z=&U4_KoYT9HIAn)@BXo$|N1W=H>*_AlvmR^^M%j$P7m3x zP!m#AZ;e@`*tUjM_*l&*x@EEuO_I%$YA~Tw(-8*;Je?=V&Jw0fAzWj7M}54{^B7_a0r+m|mhbTfDs4;5h*s zvqodM%WAn`I-6ta8k(w5BwGi+U^H|Wx= z+tlhcE;5VEcgbWOE%oTsO`<}iBImT4Hm9k@Jjyvgxx|u13|(V3TcH&xQnSm_3lU?F zzNMf^GTWL!Z_wbwiw)N=PPsg}WI0+eJHO`MehcZ=0iT>rSxgqZX$gGgXI?{4HQWrI zO#`ZuKwOH9{R~3}MV4770<}hkT$0(iA!?aplM?tbVGxie39G1N9p%iu7$Hr#wclg- z+7XYQo*`eI(-?F?*BI{hIJh<7-FJ>q@|0&ke1u%BvRG~ioq%qqLVc&fbi78>RGKw| zo!4$rPNt}BVr5V#8BU{}t?9|xW-on231{aGEyY#Wd1jEod4OCKRNxNcFq$##0u+^-R zpnx;SuGSg387LaA(PR_loZhTyn=<T&+TB*jT!X zU8!Ii2C^a}$_lb!;<*k{7*eq*Hfou%y1Zc{7&tSBw}v(P|Fy61_kQ;w&V0kc&)lb9Q3;ka>bl6v38~5o z!-@vFiB~`nMVw#Gs3`)mAR!eQggy^;TQpyLgUGBgR1!9s!n0LM*OZYYksn=b$d(gy zp+L1NJUyMUYozq{_Bc~|1hWa2Gs2zE>FH2(w#gKQwc}9~B~q61`u#nm-VnhH*?aAX z^x!t<&yMNX5|1xe)PfDa{Kh_&K@Ts;FgFgnmPoHxK_2ul6_sgRAkUWk@@|D|H0Dmo zc2z}IR5VRt9p?mIKvATmMaIUD(ejj1gj%z~y3!(w6IzOZQLB-zT~1FYOwMoU-`Phr zEeuuRN8kMvt4Nt<0)Ov6`8LCr&Cbui#rJ;rgffb_`|ceEy*jF{62~dVa*m~&Se*vv zPcQlK!(+zh*Q}y~{BlCWQb{*1N+|#$5+#i?XRobM3MEz^Qqv@;w;=Km0I}8}$#TNw zl(!mC)H~#5$tHzpIb*L|rL1-tZ&H-Vp^`h~szr`MwPHYXi$ao76A!tyMJB5hn+5qPr3j0ZT$8Y^CxFi1c4Bl$<>6Ble0G4*t(9xq3(+oF; zwVRRV0s~v;tAF8Fxs+7WwTmo@H0vgYrQokUtTg6om6BT)U;dc~EbJPq(U_*C;`tHr zYDw2tQFR@~UtwArv-&o=SmGKD9vzR+&Y$zzVV7AfQQ2H_)Ul}58~7;fwoQ!N_xbis zK`WRtD>O3M@9^k&PH}QZvr$Fr4@g9j^~|N#Zqm{fey(G({q|k-YK2x55T^n`3RBmoDP%NT zRYKiBNK%@*PQ^Ca?KUx5EtX-19eL~>ZBrOF%hiU{i))T{+lU8;{Qh?zl1xXOtpaX+ z`995q0m*F1?fo8af9*bUyUoGj7FA8+@Bh}vY}p!j`!(8!LmqwSV=m?!zWJ@sF)uEN zmK(yPpwg&fbsG4K4bsNLsv3k*OjQvO8%@MGpxUr8bp@%+$vuxK2+&EHE*y5uoP6sR zf#)-K0`L}O-V#+7d9j9OzG5&O5{eei1itgvPiCus$QPKz7gQ7xeRa3~ub9OV$>~8$7|%16PoQNS(;)N2?uv? z(HL&wgefPN3*^m`(AjW4570Ja9`rQ=QAd@a*{UOIHj&vt$TQ4}%_sAMo2M@^!xd+X z2tAl0_lCT@*-$P&7ObO`*WWl~=k_*FfApAS zHm5sia=72+wRc|U-mkpN7GH%`p?s|&vR_8x^<pvfZEaEnw@sj4EPSQ0I!RLX$uL6f4=CKg08 zca3Q(Wd4HoaGT{Oq9H`AM4KopXsbDGB}WyYOcIvkIZ9a)#s%~18}=&-Rb57sM2u>U zYQM+hkxzPjjA3c`>ow=I4KK$LSGhtdifEEVy;jB2HS*9S%1auJ21ODPdLD*pVi`JF zo)c#UrKF}J#Xok|!N27uNyrzN#246WP5qBnTkZQs?6KEU=~ZRQENACvkH?#c_uhYj zAxj*8_yVQdBu`RC<24mi<7%>|X91E(;0J8`YqqLY?4x~*s!gj}L*Cut^LfbT;)d;t zME`J~<=Vr&JY~-osBR5ec|NuPZd{P15qXl6gc0NAhFdL-WaHo^Ihml+vUQFx=X6bh zYNJkltIJqzaryETSrlk@T2z&SC=7_44T7%IXt!wX?{bw2j6QwB`s|uwIsyr*I|Ejm zfZ+Uwp{?VJ8vprso^tu}lCRc8ei+HTdU}Nx#n_h2{lh-3{T*yg=Fv1HcRYUOYxhXI zeV%>#gdI!ZXaB@65STXEXvXb(Lz+#SU;Fv{Y`^mw>2$)qgAS&m@UQ&(&vEn%UnYNb z!q>lYgxK%%{one4-KN3ivoqXJp0mH(rEzDE(K>=xFWKI1@jI_p9EuTdfBhZCW{vNC zen~f&v(>1OW*MQg!q9a>RVAB`*=d+)mO-#tvB|)j%@FMhi={)g^r#%%;rT|OEr-OF z4zuYDvV@vhA+7gO41<*$qdQl;c58^Ix6x#oFv+Pk+Zc8QN3l6|p%yqa8#M}}hMs4X zhQT8z!#}^KS5c|7Te!<5CsUte2b?4a0s6yjO2eeuYLSE?NtPq4Dik@Is$f|rQ4k=i z8osk4i$Y14r9b;}w!8)kzQ82@Pzd~s@QtJHUw&uLKG>0cYKB0fm<;dUVmTc0&EI>- z=4wh2hDfqZlI7^SN-o0fpMQg+gFgOr!FuDdP6T=l6RlRq&jddD=s8N@&~8<^xtXCy z5$!>jn@x-nxwNVl2e045ul3Nw4W(7ZSuT-90V1C=T(Z|TDTlYo^$O$Z60t0By^y+6 z&}>xkR&#vEWqC6~3>>^TM^IG)K_T)Zs)j_g@z4~BG|dRdGg!`%g#^3PV6yTFq6D&% zovj+zqZOiR6DulT-L>exahu6#$@<|F1ZTzTM?L&fhB)HGWz66B&wj++(&ra{=}iWA zcX{>Xgtky}?^l13$ImZ#yQXmW&0EA_%-*dYa=psE!!D;Ymww>ztAFMfkR+L8G-Bk% z{OJ9cOn>k(kDgxe-giFZ^`6C2G1!oO{%pDlBQEg60M3s)z+zGE_oCn=Mmky&Qi1pRuc@dH% zJb6XoI7nql9wgi>eSZHc$5kwb%__}Khe8m!K06^!bBZ*fVw*&PkD$slI~{~9B?toI zECW$Qmeqep5aZvTZDOA$67u*>(D4Ir7Br8B{1-2mm@iNGgZl1}-}}xZZl0YI z3ni16mmCdSq<+Yqs>lkB>G?HQ7IQk@u$<0mRxH{@OvBV!EnOP3E8gC%vAxr$*=<3Y zbG}%h#2f0Sj%pgL!UR1Fh$>B7*9DVN!d z5?u0AK;jGN*WcOu*Zv1zYyZ_fyA(o6MJO^dy+XXV&&h1V^!So+wqWI_)Ou|!Qzgv{ zG()FhsuXdGb3H+@OsdTqwa6oi5?)LL1mN8_4zb_3&++HS=$9v`Wr198V&oD1Zi87N zvp9Z9PnTJWHsNx{u34g(6@+SoKr&d2Zb;TE27*t$)8TCDF({X``h8@(irVS%gN2B9 zc7j_-sQ!|!o+8ycn3hFW3P{n0ZmUY(88A!Wxi8Q&Bx0+<_3;(2?RL0`C1y`w@Jny) za;De$(f1xAUY#LbTw&@mCw7O$I-;J$=(0r8s^zNyf+b%G?L zRWb2~yZqpjR~#lA`rQT(Uf;);EcD}3js|s3OPzo8ohOuwF@t-1d~&wpjc%2lK?l3v z=JV?XTUv^2*kn;iv0h`#(5{=vmPw;sqq)C>D9O}XP0WKKCy~hJ*Xh(bxd*(S;|f+zw3qA(;YN|dr7jziKo08vJ@Y=kuaKff3|{}DeWB)(wY z*s8tr*M4pI_wKi3DUCeRBE$7FiroW}YLySa`6Kcm09i)VbUK|Hwr!AYe8v|u#5m^c z*(q+CVQMn%TYJPSpNsK^R2GoLoTe@jB~XzdRdssZ27bLkk!4ic4d&Mq>ZXR5!qv$M zZ6aF3A%2u0dn?wNh@nX2qCyD-g@(Gi;!AJrG1J<3DR{`(p~GIUg0Q%uuOzg)9qeA4 zXVZk2kDf7T+ibu2Iv-woTtE68=2OZNR?7`q|-TjMTpj@^JM0u9KT>tGfvQ(X0v^ z&qYAQkOhh~LzN}SGmEI~$i9!RNl3LiJ2j2@t8-$_L@6^OLBdi*=5ECH?LF2P zBixmTSh11fh~*-nZ^L-$Qn)F%_uCl#Hckd-Pfn>t3#57jXFSCcU==3pX%PpvcJU>H z>Tru`CL^q7xN*+&bx9b6Xr@N9*CF11jSo(j*z+^4Zyeeh(BGvhmkhQC*zGQ#T)L=2 z#!=V6U#@U6*eo|3>M83mrfw@}s)!%>%%loKEg@<3xtx2vZDb4&dbn;xW6(z5+2W2? zP;XV4IX+TVrRe0 ztK%`xM?O1MiK}VIEEm|{ZjshoOh+r~;RZtyFja+Wvqm8*2zkbxySKPdS~!apiCN)t z6(g1<&U!;#i0D|LiY0C;aD9G_?M;c|n7Ss=GX+XS&L%GPrj4>SWPLqmOU((Y1Ljwk z2-8dM?sbp{`}9qb*4{27zd#Qb)GU)yv-!@aC+v75-u&6OS?}H=o-atJGh|u9Xf%im zky^v%;XI<}jOlkP%q9!oe)le6qlH3&S|)Tf0p;ix4_}OEPcPVNsTln}ilQJVG0A#~ ztgASyHTi6cpc@E+fL6xTEs?`P6W`BJLJzG`#q(pt)TdQ3Xbgtrvci1saz1sqqi5V2 zRM^_vBC+da>ltF?5XBKgJwh!)3dKMZa%7<()@u-~s8lSTPd(&dj@sz55Nw);h-5do zoO$e+1?vQEHFd(_JWBZ+ZsG>+1<)}i2P-I8~I9W*;1dN|u z^X5*2?)?L1(+#2^P;EB}^eX=78bt(45wN73-1Bj+u92mJtzL_R{Qh&tQVo=5rbxokt zsUdZTjLt7;5ff?^PET(z$v7QvxI8|G^^&fwL90m;#k35OFwJ>wP(e62;L*hbzgae^@yFlF7eJignEli(Fi9~guvnMPMy17ex0=1BlBF! zB%xB(@PZg;wIl@;QHW`pBvJ5}Zx+c3KV>Ao0RH69?EkC(hd*=h zS2KUfdbPwTVx)GT&oYbO`rcEb$qdI&=;amPzEtTu(g`0UAn9IA0Ow$0^;0jok0^YU0sMLv%$VlvPUIz;`xCWr}7Qh>C)4S&XI| zkVMSkfDaZ0qnX34u0^F?ClnQ;G-K^2jAD>{2eHUVHItKhfHuEmr&mF%RuL2l&0n(9 zwJB7cXD=?Wh*>!~WcQHr0!CzmVo<&5oCmCJR^{P>)~ zPM3D-^QM)u$>GT;<E4{Dl3*x4VD(fAfw0-|46!zO2)3S;U3Hr9L3)w3%H^IoR#dl2U^C zjH^|M-tKXrrd;^YyLU*V-NZIDgpI>|xEU!m&4H0E{i08OWU%jIAHw=e8 z0z|aPqwMZ*bveQamb3?b)K(uaO4yYHZtr(_9+{|RM!jM&S^GFwmlT0Vl0<}yIW09O zs0}z-BuEHMPfj^(s%+XjWV11E>~&CTHR3Sh!GlAZhxs&uMMk7Ha!|HUHFV?8@ zF{>aUQDlT9LdqhtETJN#IGKp)FOjMZg4LX2HQ}2RfzjumF-R7ey&i#Tp^F8&F7fp2 z25)@D)}YNiEIE65!s}MSo!h%COP$B(Q(Csn(cyr&)#tsF6}9jhOBGp-Z)i6R`T`#b_Cjt>$cR_n8@6yjY{Z1=M2?JBpFRn2Tk^_pf3;T0#k|b5ILt z46D5J^|yHEYp> z7tywN*{x};9FNBS4iyEiZZ^yoJ{>7WNMnSmg&MijMhYjL?mg{ zr5vlVy^yAyb8zPtW^aokaJjy?q9<;+31w>8 zikhiVwJln$I)&9>GIuyoV=8aG$sa@(&wunegUuy^rV_0ebW8&Ju?sgb=py(f{My?CzVzi=+`qfat=$%T zg9dWNV(a!ciWjk7dgSC3c}9}vh?0b)s9Bz;|N6?0o-QHhUm$@W4~d@~>3{M|gMaX= z_swmZZA2kQZgp9QGEb%(KK<}huFmHq$jJ33?Pdkc3ftRVDtXM!^#rNe#L8l>PjA>< zTo9`!mZp(;K62Gyw_9g%eoYZaOy?VFhr6^}Rg(FVXycQm1yPuwi4vBska!85oi^g$ zHmj>SwxO}|BN|nUxD*f+g=H#W>k65-K_aKNy^W}ARBaPqt6?ZIn<(Raw5CpxV|24%+m@MmDYKg~y=Ik7AyF+tM5BVPNF+!MwG5@bMHFZ3woSa|J}0j(*s^6L zO{G$V7~9)?K1=xg$r;AwbM{&~y`3#AL!;15{H!F>OpX(kB29>+h>EG8NU&wX!M$5# zam+w+QTOlh9apCj&Ux^qH#vDNr0 z!2@2N&&j9PG)#rCe~Zg?PQPy8%T@AHqAYT%hQiBGh@2DEPvc$q_=2z|VPansBj+ zm`ofrO{ZrH6lFo;ddx1aS%o=OZ^E->g5B=IWXycICNS#gl0-fm69bm1Bj_5cqEILb ziYOu(2A!JC&18i#=uvCd2^@#mi}90;^FqR3Ib>^xBFT^ym1Mm^l4T~>Q}WRjO{G8| z4sjES!gFa=byi+N7KPaTJ}=i9!T5$9yF{`otTTnGZQ^?&>g? z5F{nBS;h9JY#;6t>Mb^@h>>|%RhxNfF?xASMac-`f?SZmwD{fcJ*9l{l7XFb=l&si zrA=9+_|66)+;Dw8h2>JsEBlB%-RGHBK;mTt(|&78a}P?CU8ZeqmoF?V&JnU^5vA#JTd zX${%fTNK`csv=;B0{i_sY5S1tM51HJxKf>wldv97*p)U6J9Y9(myb>t)D~xmS%JF= z5hRtg6rtL}i!vUx6e^V}n}yHT{R2=9E^n6ThQTAV!3RHh#GleOY?<(Cl@n+1%7v>K z3`ykY_FLRH5-!Fo3d5j((4|{9IC=jm7mtpa&o)SV+f+4`(RhO-3Y3CCk!OfyNf1VV z%SrMXKcyso0{-T|_O-wMZ+yM=-xo`dBnT<;9NDZh$t#@CSJYZ922BgCh;W^N&3s8w zlnB)-YNf_@)5J?k6ivl8WYj#RR8^Y0+XU+s%UogDYY=RF>YXN;qEWGQ!i#HGQARE) z)N~nDkti%1FYqbyl!qIUcLoNr?-ThcHA^FjQ;IajR%Kef7Kvscy zktp%z3v@#vmlcXAL@rBAu|)3lDKrC1k?_&D^hzvM!j}wgu4ZJ;3?p@Ew;D{1K0o;M zgkG}1sMSy;39C`3s~4E6%xvu;iv^)tqo?N#w=A}527|*x*3${Kd_$%f^s6clj#WuZ&TPr}Y{E&Y@Zin>OBb1Ka)KyBEK_7j0t6vV)AyEX`H(+M0)J>Ee$4*# zyW4;6fAMQu|E_74E`CZ19A)lR$$wL=ORuNX$WJ!W^dB)Ff$(WW&)l%6g zHBL@0>1I>(cAx81Y;^{OX1WM!}0!%G^t7$pw2x$yoqDoWml6y{gWy95t{=2uzEu zoep~F^X%y*fAHB2p6h~~Bg!geR$^_n=+!JPCLv|GLD6&yNk)>SFOU4>e-8pbjU;}I zwp+&V-}#qc`+N5e?Ml4%Pz;^r+~I>4GydR3z{As&8%IJb*6i)KN!1FLoOA7$40pQJ ziCL~ToJJb^{W=X|R&$4Sn9K;xFi10$Ez{Y*|pNS6FH_V#i@i z3Xv*JOj#gNO+NVilv|QVZ*Pa2Re%<4IO-ZidY$LX9GQacjzL3;(DI1AmW^gxIMXRg zQ6P4PjQs*Lb9s5Wps_mR-7nu`DONCImshiZ#98pw*LV3`+~WNYp0hQ5%saa_)5{#8uA7$GS)z(EiX;-K7RMuxY;why?hKF) zU*m_@5jUSd<=w8yd3~FwHxAxt%-8!0TC2qelaTdvLAP!Y&6XTQ9*+x~i-pG<7W54m zh45P=*yM1lQQ;eRTUh>*$#jWOrf4;rFiLrJvS#il)LK;zx;D zuOL?%tg(n=fiLZdh=tGT&5CNP$sHr)=6Z&D>vg_*P$RlH<;CNdT=^mo1|}!RS16vt z3Kjd{fJT`Tuh%HL&U!p2Q#F(lSzG3f+dy&TF@c z+e7}rw;od4T+*)S)QPEE8r^OkLAM#*%;?)9Z-3%hVHaQ2*;Y~(_7>02Ck(49r*ofSHl|iL z5lWTarcS3SbG3|_hdJqL&cMoP?H!QII?DW*qd}9fkT}??kyQJ5ixqpC&l}qnCfXLK zPoJT?6Iz`%t5l&VOWN%gk}M%fB5~`0>*9-4F1)x@9Tf-zxVau`Qv-} zFFA9E#nR>RWypX0S<3ro0ij@nqOtNr$|S~*1d_#whTyU;RAfcPP)b6{U{HGe==-0t z%w+=4=O&Tay|qiH+rkPKT&zQOEt%0K#M;@Rt&3dDJWNXmQ9#|@rX>_yfAWm0v4h%d z(5V=lolOaKgPpIvK`Zk4(F+$#mk`UGr<s7}^p-S)!F0+dF;yN}Jha$-_^cqNxH>cZbXK5w&=Vt*Kmu zGVbJxBJeqs93sh}sh8B%0;Sp{kaS{M=A}310%;N6fR~Sg}-LHSfffJl}?XUm{FFn z!sOYDE6mM=wv^Ja46=HkvrMPDnX6+4~#+^4rzF7&!}`+=Tq*B^@^| z(Ze;uY{b%usn{lAA>eF6`hrijUSqjh({EN-dKs^-mMms#wq>7Iv7p;*Vwx%kyIm5= zg4GQzIYdk&I{UXc9lMyx2Cdo0vHJK4{FCoJL7HFiwbyo7^=|Xb6REf}+QJ&E2$9Sh zsi+VlV=Dr3?9<-eA+Wn_+AqrChG|sQ4yw#PUv&$+-=}0k}Bw+j_GJH)>GfLFPJ^YC-}mW;M{#AN_SML@mVVHLv@C*$R-8`?TJ>xeBw zpr#fWQH1a3SaFE1z{egO`!J8-yHhAMlf6cTmL+hfCBe-NH?JC(X4Y!DR{7ma8$Ckg{p3OcPOrDienQ_io} z)bXg44x@>KUZ!|KK(*UvSXW3k4u)y5-89)OH>9mTTirUDS!JLVT)n&??F^_`21S-3 zA+mgV%;n6byT47Xq7!>QR~Iv)yre&9v3PdIw3OJ}YjZt!`EZ<(lsbthGR+0%LCTJi zqslV1icPaoN76OwRfAGi$d)TQx`p%rz2hyBP!iC=U$F`Ibv(rV_xm@>cu%+kEq1~ zMVz4L36*w>bP*6cK3-Cg0m}lWDSW7>Y=gXEe8Z^k2J;)ome!IYkmuQsBmEU6+-& zZoK&4=bxFtPm07JqHlcdwWB}wVECD?JXWO;Hl8!XwX29e4JFks2HrH9J6MlC^Ax6vRrPkcKTFx8L?ucH>&8h3SOr0>dN7A z?30%TMy*M;S_M&Nu?g`#kFFtMHfv;(LQs~NTRnm}!%##r-6Z!tY*ogVC1NyOH^9n5 z^!^s(>nWAhC5kMem^O*;(rwk4CK9W;!`4oZ7aOqBfIQ3aqm0y9ac{3nXRFI7RnTRT zJA(#dyU&xG5S%GBrQp@+6~pp|qd|wY+Ci&Vxm^Rtk06fF3cv->qc+QqqQfYTt2|6vkWbP$A7+A~$c=7OaZnt%G!@?6Z&@H-ko0qeI@zs>| z=$b~npdyz@cAcb@*)|G%qe&3wI4h4lPN>uy6q3k~K6*yiopAKvK8|eRPnT$+ORnh5 z7asY1%9r20kEB;w-OSJf7s7^Lh<( zf5SYKuoTG4lA;vMrfIliFZzI=5)yxie(9Zi{TC;rKYt#YweiwLk`+)i%GEWpP#{V& zmIQ{bqf5}++2?YTqQo9TnIae!+#q2zPtY`({b3cUEXWFxBJj|4l}_RE@YRH{l&ESF zY93SM8J}Id>_50q&$;CJjRVad9YbL51k?sy)Ffsdq!e+6Bna51!t83oA{99~+wk!x z=bX)5#A*%8wh)VqG%uhmnR_9NLd6nur1hNTY|Z#$Lfh6zWR)z*ab_zTN=a>dh@>d^ zn*crb*xKJAku}8mjQ*fU=jafxknkNJSyh=kKJN7uk|1CRB|?@mx*nst3o1px*3J;O zRGFNfbJ#V>j=sdVKR%=4TypPd2#SG9#@)LIoMm;Sn`0WC4)2F`j9`hS>#R$i$Y}7J zPaIyaBv{Q30wP*}o10ZcM+`aaT6DT?Ho1(yUUNNl@D~$0wJN!2P*X}W#pEiGSdXsg z8UnuAAsmhAIA`osW$KM4s%B#J2h1XvO&szxN31pR)-H$rDtdpwMl=Ynuh{QakPhz> z2N88uq7-DN69+8{81|cpw+@-jJ&NmV?6PDXM9h-}Srqtu15Y<_wE;!bxYepKv?adu z#(*#FR7o}-+4g|@yA8ajuQ+!i)a@Pa>~=|(D@K0G{&tH?FQeV6BFxA5ae`Rp6q-S0 zXTU*K;{20`ocIC_Srk$!&`Wez_DB>oV6`ut*MlZ{%P zt*?r*R4W3Hf)YyxLzOV9ZE{gT(M@#SU{&aN^J{9FL@X$H&Wd`Yfojz`JsER#dP>C- zso6Smny{WP$O-|!(nW4|5uy;eEC>XhW}}Xs1cZW2Cdy=rikQUYc}e6a$hwMQXvB_- zw|3ZULQXC{p1z!MGV@r338G!Ws#TE;6Is{tn%K;hC|h5oSU2; zUvbd3`EaR_E~m`A9NC@n&VHS}Z zWJHBb7Ns<86UnaOC6KKha#jV<;TzLUd@suqQr`sx3cXI4mBgV-8n_5n8)tk;Q;I1Cfl`pk(-@KvtKLMc zc6oNOpko%?X%^hLCDr~ATgVW^f}U2gh@sMM;a**$X$o5AlOr%6&G4L%H1tVSold_+ zF`Ka&jd6m2>!QZxTI76_;v@z0w4~H^EXyR%bG(g%7la6^hAgWDNrt3pNOluPG?4lo zzSI&a{D7xZAIo2HbbCmon#|8`5H~LUP8I9cKB6Qte|1TxRbkZ~uo=(Us+o*u4vC~v zW(BoogR6an@HB)B@~?SVnH)?hWA&`=BXY7nVVfk9;Bs!xxV3@djr_J$H~PUI}do`D~M5ozO~C~rf~7(7;AJ+rCQ;Y z*q~wQ7`n#AI;6Nd$H)pQ%^DY4jmJ+fF&1-#AZEGp@Zy4oB2$zwzMi9vMrc{WxP(u9 z_;3a9%?eJul9np+GYy3uEu$xeh)28Je&djJl+wO`i~CKT^5Tl~%LSEoom#)eRP zW)XuzK`3h2iH{qmNMgpy&$)JG9?wf=LC(ZYnEC-_mO+`5Wg`GsQ9xbHDK;*{VTbx_Z*YDwrQ)w}Hybo}#+{uOH6f+DwZ#c_ z@HVvDb=*=Th%>G?DSEI$5=*pZi$x(5j;`sM0{3qX5o&GLlL@6Hzl&>fVxi#p08bC6|w1 zajz=V9`re$xV-%A1qa)0R)WU1C1X}=Y)Tbhl=#l8Dc;jd?)3~Rw~tsZ)~Kr)YO~Jc zMZjpb#!cWw0H1pTA1~pF4+T&a;j6E2^Nl-gWFaH6sz_Nvxm@CzHuqoK#rxzjpMCZc zzuDoIC9`~W#&o$M@Iy4qz^GW1oi>`HQbsO*DbTugNL$VbqKL+DK&w$jSzO~f8-g(A zg{#sVblI=Q_+=G0EYZXaimYGc?AqJW-H6ZA?silqD}GJaEk&=? zkW`bnlnK%TRT2@(lvO5?r75U78$W_9!PE^Xa%4$D5Cwu9S5ETWR{Z4|C^gS3D=&B+U>O7PVdbXzvPd;4^Ewh%p^_30U> zFBdFjh2eG=)!lIJM0A=qi?eIa)(Jf+;qq#XB1ssQPQTY+(5;|_8*<%bUrQK`SGaM( zv{30ZDg-x|yc(^Th9zldkFO3@oXIusU1nsZN>!JT6@{`a%+ixDuQu^RzQ81YOu{%g zxqql7(Qfyqa*!C^))%NLU|`MIp~$UgKS! zaX9GUD^!g{pk>g0;^wa>REDGx7W#2ii%g-kaw6@@%WP_mp>RpYg$OrvhF^UghX zw_8ZEjHXBgVM>xlTu#>1Y8GM?QZ`%E42_#jg4C$fwq^YF2H*Dy3W0v%v3m84=b_B* zphL2DNW>CDED7SAR^6gft0GGRvjEyv17S1cH$PtR-qNPo8(@kVwsKrHH1go1D~Wge7Rs>lx?Uh?f{ z9##tHLoPN2ZC%6>4E(U5+q7Aw3jSiljtP-o;l+(deR9T^_uJGS zyv`3UJsQ(1{3s?2V(t!F2%5>mN9Twem$s&1+}h{y(<@dlPRO$iKZr0C8BvxA)-Gxg z5SvwA%wpag`Or5Bq@Tbl1CXc$HS`Ec&#b1$t0puBdu1sJFHW#7tDf` zo5Ez+tF!V`wg(MvRsjt|rJP;j2@<8*jl4SBMrz}fE5foV=&tl>*L^n)i0T2Z2N`)dzP!*Xx ziOKVvN~KC3$9S71nrRXG9@p15VAKdzi&3c&Bm#LF^I{rtc`{`bid^{x$5&Ijc|fh* zM2Hha+amO1qNRgfwdl8-ctK1<6^RuCH!65_e96yrEvoGnmTfRKYPcsC{8N=~mrzg{ zO&liY*EGwR?N%MR+2w<2!t(r*pF8UCO02PdbI$7KY71uR=b)CX5npLYc%6Ar*f2avh!X1tjrf_T5ikJ=x#eYFEta*K)}q2^>_-Ak7P;EF{eZ zWLZWmOH46Cl?0+(KrC}qS*B2Qblt?yGLThVxyA9th_BqL(9lZqEaPJC5mdVTd^=%w ze#(b8F~4yv^Joc$q@f8pWtt%58EH{cmI7H`kYpL6D4^*Yf&d~VWsy@-qN*x_C{kuA znk-SIDVnZQ3L;?`qH8*3mLN(BP_kaFQB{?qEYX`yhJztxQIO|3D?emh$cRZq6b4*{ zBF`opx)mK`xD8ptR=mywWA1DdWKb&;ULV*f{ULb{T3K@JW-QLm zsgt2Jx@=ZHS(Y)MtmqmdMyJc#YBKrcAwN?qF^}#r5e=$|j~fd_ixqafLQG;5Rp)pa zVG1R(s-r6+v7mE&F~=}erkfPWb2;iaX?8k!U4>i_i;ObQP!*Y? zgfNN`MG3>Mf~X>^DwHK|CP1E30Q2PvUC7Dw8q#%gk=HBwof@g4qM16Qn-%$Zf}iAwy#cyuP*$qshE48yuvws& zCAw}9FIUt>xWC&aF{_BG%2g&aNJEDAZu4}Nae6r=i88b}<#xY@-e^N6D$rq7PK zyW1gZbSNc-Sy1rmYQZ{)m|afU7EMK#?9)Dpq#7+S>d-k|m{3e)R2;g(&kG?TnQ(=9~RKtLo< z0^(8vNhU8#!mOZ3Q*>1%%?m75AuCH3^Erb~8==0#dOo2{BUW>l&mLd#pML1@;Z!9K zTy$c@JVD5FqAVw;{P)wM_@Aya{+E85{Ri*H>EC{w<$rstZaj*ze4eK1&q|6)QIv$C zPf?VJ0_eIavq*AS+8U|3JC<=-slExvLZjdG^VGtq;C0S9BXE`9E z)*6_miCC6Mionbb$)kuY$$4_^ar*ocF^+Kb8s5rBkwhw4OidLL(u`WW#&3>e9)IwH z?II-43kHn}y@P$cTtpSYx^s(<+>+e$(N&Fd<1wrlywDn4JbXqySWqo8#6qG>OL9da z)os4@Y6Z(Nt#+L(OtCbTxgU{DXUK6#LoDdD8nhc##9oUZ1QOr-}OcjDuqyT<`<~l9)+x;ST-BiB`*pz-M}_YG({mx6N)@X7Ddd8 zjVwv%x`wK22xUQ%MEG99bmb%U`n-LoN7qs)$`Y~Fps5R_s*Kv{pqU1REEB2*Z|t`T z^UvN`-30LeVr7 z-5|?S@+?Qybh07`Q6??~{IsA|ucD-Ww`yunuAT6d{~rW?{3QOc3H+Bjy;`_;jO>Xd zXMZUy^?s>ZOcx7^EJM>&B)!7MbrBLDS<$dm1yPm=qm&>{soEy0W+0RWc~Ov>O~$Uo zk3PTR{ga6AJl`;hWGpd8%rmkiB`?J=E%-ZSUi^2bY5DI(1sD9kok79>!#YflgEar` zs-=x(QT~M@&-J_nL6pdn7(oC@l*oz_+cMCN3Td7ac`g(MrfDJ+1(KptrZJMLqU$;-&?Qt2wL5jD1Zcasq0WhJ9<7g`4p9oj&UA13r2>;#RMLI2`if ziz)y351t@RR!rQK^U;RypDg*_wa-N+6%E}q$kUWGO^K73B#se9 z0a=vDvV@|@kyMQ^iipAxkrILbm%Jz`$`VS*$dP1)#nk2Mvlm=lPZ)mr9y|Ry>BhtC zv^aSCHtn{Jnj{Dthj=#OVi91HA>|3ORN}-L4IT10CW;cuBw>6rV_Is|x?QSyzz-hJ z_?^WTt-&609ujOE!oVl=T#7uWD01>NA@Vi^zK6eY(5g)ovql<6t!C9OJ9Yd0i@D?R z1tIYh^lBN#TTOGd-);WUATD$gAEiieGl4RVFbxA$5=bSDO`MSw1z8x7B@uF&lByMC z-NN-eqRom>P#F6;ekxFwIi?~Y2oNV3d0xCs%KVq6aruAo3(onk;K%7lvJwA#QmLvX zf-MU4L`f#kbIPJX(=^f~MHEWn(5IASk~AaF64E##$x<}KB#i>1IHD*^YRxv1B$0+5 zX__F25{hLZlqKtpi`{Hv8a7FqQ5ZJ5Dv;(W=Rt{|W{|`@UnZR1thl;aa&|W6%Sz1c zVGE%@L=t5_I-9e;nQ?kL!cIdT9nZKGI^4c@z;w1IpU*LEi$TARUrH?3G0VA!c74O( z?g1;K!szmvLnCMF=oTjvmm*1+$rh`tCCfzO@1OX5^!W`+5cAPh$ZvgiMKX1WfhR7^ za)Cuw5*Zd|e+#=mq}FO9$}*Sd=ZKPsq^hKGf}*KJK|mbE$fAfO%cOCNqNt>40%d_H zfGmp0sz%`ZguX|bCX_`%DF}pV2BJVAN~{)ZCQFaLt>C^q<@kCDl8j7Ag`DMT#dzY- zHYKX98ZTa4GK~dxY6`KSQK~vMA!ohbp!BxsDLKOGhCg^7@dKxa-sqyrkfsR~8Je!6 zsS2v9A|N125}IkD$RdRxP?Qjc0ZyEOtnI4AztL3e^~iNoz5pbC!p`UZ29EZkTNRkj=&=-mH+y3`r=7 zl9VhbAkY2=MgDJ25}pGE|9^@iVn0rQrzy$5S&%P_f;W(5D~)4BNkSAw5CsZBK#>&; z%Op!v3Q;CcVb4iJ_}RL4YhP z2&~c^MJidPkmNa(1+%!oOCT!+PTicFn-v$!kbE}dz+bXwDpb;fURlsFM1oQv@)DAT zL%m()ywc(Fc!Yg%NjFcanj%>cvPt0jW{e@od>&amz25Nhe98AdzF>Jh=hIgUp1r)G z$RSQsUX2{4aYoG)*dQafyEvuDCe5hTo0KKwd4cPCxQ>HRLPo6siR1~p9UET0^KZ|&O)52&pS>BvM zSt3g!X%eHTI{#D&2m+*Wf~p%Rs!kq-#GywVCx{fxXN$5Fq^c!`zkA`t5nlijUjXx! zKkZt=RdZ|SPh8H{dP6SAjXGYGAS6DTBBN*~X;DI+P}LNWb#%i-5(^AXWgcZjfsZC+ zBzZv;W#nlxCe8laqbUEIZqA&4PHvWM{3QEs(^CI&9;Yu$QT$_ytWXpg1p<`Ad=z*ky0For5>KYU|vF{Nj30Ad+L`j|(XjTPHgglCnixQNHeBU!OYL`!kEos&3G9QBspQ4 z@cGFSeKlv378C*;2XHcScy_(uM>h%MP0n}E)?BOt{IozX3)XqbBF@nisF)IwC=pvV zG}}h7s@Uy5dZmK1T2qt)m0FD~OGuK0^5a0O-072$W?30+f^#Wr2V| zndcOFMo~hRrQ}74AW5i-f-Fjil0sP&2zgF{KvonW2^4}%E+`x{4fM^FIL_IOCp^7e zFu1+TPF=$ZGt5?#mXaarCR@8*%y7vEpPjKzBs4?i(en}CzL0t3+GI&cnS_W%L5YBE zR}d(XWR)~c2&0%X&rl=*Lv~dW>sK~NPlq95ageZy#f{3PT6cl-eB*_S(K#4#ahsc6} zB*~PeKq>J5RF)+IC8Z=$<~d@S5~c#Hb%+%ClzZFk9Bkn@KGp3ZEh#5JVgm=-pBWynU#O(hL8Ufh`bDzmH+U( ztbeYPnfp~;ok_Cht_TsK6g~)+iv=c0(OMDe5)mWKb{8QaU(Asvfe;WTGB%VYBw6i#=(TSog9b*Sdf&*p&Di4W(mV$Mp$MQQNC`d)ViZULR!U5gVU$KHjngSkCyW+LMvEodB(!@ys=8u1pVMx( zNE;bdUZ9l1hroO?1tKv<1W=VZ#u$`VxY|Mtq)CF&8s{u^RiP#Sn@JOllGv)k`pD<_ z;6Q*aD`M~jA&4OmeZYr+6cAj+Aa~RxxXFa}#wt%;TtnCjF&z@hDQ-SRojJ>86eVm>E$ zkE=?Ak`zTrF&qBojs3yf`Mk&pp*Ugor{&GdXIl5y8~WR1bERFmfD}O1##xK>mP{+6 zHXIj$;dp|rt#dy7F)sXlRPj^SDwe$b;-a!2>$lDOWC+hzRrUHLZLBsLEf9jmVo8u1 zDFx9vl$7W+B{+v5qVc$@CT%wHK2X;+X|q9Q3@UmOJS}5TzCxre8kwQ4N|cP09_j!_ z3bHh1T}z}3xCl1F)Im!??!iStM}hTF1?WiVYX|}g2O>aE!NS7QLrX#gf`qY!g^x6h zB8h<#h0_Kn1*P*e+AVsW4pK;@fGjmcABZth6$MfXkP@XNF$A$MvA|8cbfl`sdYD}6(z5rdFiIp zqW)BSW$mY1TFR=b95Gx>6OED*lcY4-9h~m;$jxtc^k?V#IfV3a_{ zKqf!|d4wnhE2&1sKq8=wf{u|i6$~w;iNeUpK>@=C5ChBkf-K7@ zmkWfHM4@or(dl#$F%X5I+3ORneUH6&@Vz5&oIr{b>c-*p<3_9BX{GAxgKlg$sYn}5 zj&sZ2@sP=~M8@zlUdbQ5J6ik-Ac4rMBW`Rg)y;d$-`-qp{;rJNiimTrsy2O95&$VB zu2?_}2xW*uBBUVrfVUM=8`3mGDotG!xVlEfNKzKO^POMMw|w(u=7r@g-~Ke;aCwCl zUot)#a{lQ{yz`sR(Vh?KwG|i7v{}En!JDscvQmtRwWo7tg*QBPnJc{psSsolVynyA z`Wd>uU|c(5*5=8!AQP5OB9Of<+vm4Ao2C?tCAyiBq!|?oV>Gt5*s4Y=i9q1J1LtXX zI(X+WiNRWnjFAWkDe>N8og=s!r3B7;g0q+;MMy>T7Go01vLtv%6aw!fF-9Q#w??Xd zWVEb)qW0mJ>zXAH_*06&UJ-eBL&Y1F=N(djl#xU$2201@#IdOh&aAiSQ}E!<9>d!3 z$CEDazrJ92G(fq6BuR*XF$qd*JPIilCQGnIPNUHvH3p?MA%d%G(k#Oy2}NFD14zVg zyO(bN^%tP#gi@SfgXv<*%=JjPTGV!}t}0wrVzL%4MwCDO(GOb8ufI8>wnI8GF|vdy#c5_e{XZmY#wzf0C=;;bbAQV5*$1R_WQ&Jh7+5~PqgABceW z4y_DjRZha%xeqJv)!4xOla9$6aq4@ZjmCkpJZTw8>%70^m{;?Mhj$Q&H zCr{+FCS^J4ZEQYw=fUB>U+XlT5TawzJ3=Y~f=I+WhYJGJYLTTGRlZ<3o3WTpNwq}B zifBC-uU=xc1&0o1*YEIq&+f7N_<7DZ1ovOK#gUafvDsyQa11&jn~b^l(mp;(*}1aK zne{Gf%LyNU{w|l^_GVtQ)?oR`PjUbFnDy5_#+BW5En=ybl18eLN>No6LQ0C|f<~(aL}G{-t+3V-LqG{h3Ca;;luLIUVf@KA>7Hp8weM z-1qQTzT=Hl2LqDT4rjMk>1oB_!GLLR1u-0Rczd6N{SnK`lW0Xxz;f>Zb?F?fy5jJY z*EwEPR3>Bn(k|yNZ?k)KhfbD|7CHBh7xZ`6$#3rSvFGozTwP@{sTj{I>JX4b+PxkD zaMtoULQ15RNbjlY8gDHKfp<00djb*fJtj#(L_z=`1+&=1l!N<2Cc|S~RUnl@3J^jN zqF}L@lV%N+6euZawL28~jIt=m8V%~IL;zWsNB>m|8s!X!BP@2UuCwhmGl195tta6&d({34# z4u{;mH>J1Q;PJOS!IK@ui=TV}x3bE5ze7_AdS_PITI*7~K&RWJb8(CF7tYX*f$2-P z_~e~qcF(TxImKkbTp7-7uj3C6q1hzc-{+Z6-67lFz)a`7aPvN**dU#h8g2(zm3?6M#k}ShJM;!!G>p``c{o2jL(chYY;~}9yaOxEm561I* zk8k!q;GF-JG|@fp?78`Tkr5--*2oY@)0EVgq)M^gPT5`&u(ie4Ufv+TeV1z=e-W3p z*nIpvo82bK;SsZgBYF)@Q%l?;C-{I#6sDOnxPQ#Nv@~9OnTwaVkwt+Imf?6ovU!GX zKIXk2zJ<_+EC$LnWAm{cMmGoS9nM%p5JFJdfb{{b6~-89XQ|2(EfrpXt4fR%q-m2N z1i=No_n;&p`28rtPbDV#jEnZ)9Z#44G_Tz+7S7Fb?}z+fk*_?N`}kW88Mi`|UmFql ze93FqHFKFToH?r6F&z%@-lDW2Rf;rC2qBOd0|N5pf<~(i-jNq2m94R5c_UWK@4Pjb z{AV6AidTW))V<+se!MJ?2D9a_uC~;*wRZCUx^@RK#;>teK_(*|9njjav9Zn*Pi}MZ z(kAKfn0wc5Fq#$2oS@llv)W9l@84%W7;un#;@PwGZ9y@dFyFh+q`%JVFK)1y<*alw zI%_?)HdmNF_X5+x($$gMM{|0sJvLW5Y;X4I*c`Lcr=D4^J(y8gPvs*BNtz}^=ZFG` z9-U@HK=4^Hk~ErF?{T)qJGb!8{%oh!_>qPZzj!dse{NA!@5xL19Ivd%XDvPNTWgq) zmDcS}t8l(=;PQ5tGV3uOmnad*T1{NOKq-lkn&=%uCrAOoSwaM9J3>fB?_1!J%s;27n*jj62ttU}1Eh^l!Dou zfs<@KeU;sn7G4`DOJ02THqYIea$J;z0Cj{UNibUDti?KqlnPhZSnm-+l4yOWvh^pH z%jKO+CqIz%|lN~QvKYxae!2!3AmvmbV>dLZL280kq z=Mh37jG-(`oV6%p5K^L){_i4&4|rF%YZ-oKFs*JvWNGIx=T8fq0CyKWzuk!M7%Zyy ze0p#BhAX>@{jOqE)YMglG6v^7T5DXMW0XP)C>9IsY@R3h{}434x_4B3gol{sM2fuX z1Q2<}?a$}Om(O=TJgnv0wGv1zvCebj)&uHt#72J$KRV{_BCyhLa&v#mV`tA`@+FJu zoV5%_ckh!=S|sOoX}2_u!y^XiD%_c z+Ug3EgBhid2wP%9L?}TBk-91g)(wO}$q;`~x$33EdHEs0@oj zz5QmbM6a0`Dkr)6rYHH9C)QaU9Z`qKaUOWh`E^2)64%!0lyh#6YkJfSYeDH8>$_W2 zNV+>`S>IZxCq3z6#Eru_b$6B4mB)DFZiiwz#WVLPBA6ssWYOJq` zN>kc^^ZwVGKD^a+;(r`1-G}D2y9)#!Qgg?&l_tMYx^TRa*l%sEZK&GxsEUeUYrOY( z??EYo55K>hkAL*R(*6=(VS-nO;?E@biV>XpA|1}l>yNd~6H>{qX(v!e%@dDpaP^F4 za&$;DQ8)xLZE|5H;Y<@|$43OMX|!61;P5`uX*XCk0X-jb{NR}A97lKVax|K-Ou9Vz zmM6KGMuz)GG&at#d*Lko%a^#&&){&M7xow2E)3pPgb*kl$PmA02!~Zg$s=N1xY<^# z@tN93-)qRX9?nY;30iBA5~($1x%i1&_Yc2sQMpg@2vMB+EWt^0d8PS}TntxR24vD; zRePE(O{bkujK(YqM{9eN4GM;PhYaQgkhfFXwq)^N7)$5CVvNg$N+>MTnd=ld2WNw*-dt|CI8Sz z8Ra!kJ$VTiz~8&U^wS?_*xg`bcbjl{mpg}+%e!5MrDIru#N(sKM=*f`D0o#wUTz-+ z%S*F=@$IkQ`gNb@-#;DCcT7?L-91?Fh?1NTk*}c0L(f8CWF!Ouu7XC3^RGFFQiAPn zN~hn!luM?QIVm;w?j8~)lse#nkW#u$A3DXfjGAZh} z4`9KcB6xIYPMt_rnp|5)05UBoU8K%y-2P2oJhEKeS;H>oi0$+2xEZ$=Ip@#x@uM*u z?QyusA#IX2Qp$r{d@7t}{fXDG8!dH_v(nQPlNs5{8co$EX(VWEc=P!_>E=3Ob&fH| z)Kw%#aL(NrI6eUgzG#t$$-CZ#hvPZ_ACXs|03u&L$*B{`MiGq?i0Bd0Fdt93Gb(7G z*`}ichr=oJ+T&3ay3I->f#sMa%jj;OMQMpo5-vP;0U;FG>M9q`ZE$I;LpmR^H>r`G z4$YMnx=Cbg1Ab+VD?N?4`2yFED_j&P2`GtB;sT!+IrXXmCkWX0i+p8BPJID_S3~aN ze@(OOfl`VX9a2W3)?_O^&aU;y&hB!4tIvaL*SL0PK+p+sG3MxSz*IDN>RY~!3u3_o zE4g}po%ZN1%i{qH-QuxJTWlu<<=_FIxUtXt;2xj8euvoGATf$+Hs;>_Lu_qHj6o^2 zjEEoS)FVf7>I;ax8nS3VssvUjiIN~iptIJeX99%}tcE3%(sS|RCcdiJJDxI1*9mJo zqz`WJp=WO+1=J>GW2McJY;tjD1qSz66cvYi_jqw{%H~Ro*jwlI>w^2A{20#-3huB< zch&vms5`%$*B|Rb$xR-c-MD65=BaHb&VZ6&T(#(O+BPgZGaShj*A;OS9FapBEfV?s9lE;qKCKX}67>9-+z!$Ab!L$8pEdTG_zF zCFe4@8wET44(WK0YX>2|~${-op zg6r3Z+?`tzt;qIAbXrZydWxtEmPO9g9^^bh&ZnCpy|0Zq*D@7XcbZIG;E!Jz@{y0;B~`F`<}6NY zrqdCP);4=-18owNio8Gu$pr@GJ@U~Zi7APVltv?km=JxN#3=T1gRM%O3#@m}kq?)Y zqXEt6a3SKNK!~u-sYjCJOB6Zva{Ay)i=!&WTh;}xoZDbyv(NRt86W-R9ag$6ws*H_ zH4W8#jERm`D?`h`ba0=+gZtD)PF*f(w40o{@EGaZS!|UPgQMAO&|O=_w0qRnQC1~M zv%!2gU@|yD1_!|tyhkYg?pfl0i&Kvd!Jm+vIm`Embh>>&P*oLayMvHWmL-ehBZz@Urw>9Rr6NYCs)EIG!E!Mtct@kz zKp2D23T0BP4IRE9!KsIn=F}@L@)xt-N_tTly1foBmTe~0h<3A$2$m2cD$Q6dmlTT` zLO^$I9cwL<@rYfd6A&H(OONl_em|{#qyVE8ju+CGI1&J}F z?G{zOBs5xRsgcGIg=97!(C&7LX%p)`CT$?3qFBz6fR9iXIn5Y}k!yG7^-pr@ktI3x zrHj0*N-4|T6-C2nuHQOBNkzNYMM_EZ9<3DZZkH$x)A5M;Y>Gr+lq6V7lC_ynCoJa^ z8m$J(7&_e^F@Sd#V+;^j&PH@P9Xh=}LPUrVV<1Y|dm9K&J+dUHULJxk+tH$WX|r6MATA&_W|N?S4aJp23LIrYeroO*dgzHGOSm)E*$y}Gmk(l)_aip3Od z5|mb0YYEnp7(?3XkThB-ZJ3P5%*G=e5v2_gsLBFgSIj3voOiUked?;Bc8(|{t}F6qRm9*C zLLo$?sFx_CaUl?5L`#J>2B8%pM3hd5RZW^T2?6S2fp-q0G$L#K%WFro&+t_*@+ecB zIl?~E%mtr|*F&UAV1ObHL&`J}8U@@B^ zL}dN!7Ij$?yho=Q^TiBp4Bpn{i#fHmNTq1DI|yrk>1dIEm{X55#irXLVn z{o&=SyRs-SfhLP%otL}ytn7F4xG3TQN&5F!YWO5utnF$#oEsOuUR zBeT(nYCdIUb%l1ji!p`}0@K-y+66S_yNApAMBhjxEML_(vS&;5Kh9W=K>SNzsyZXCgq>#~@VzwwV^iMW- yJ90d}Tkh>q@NyAA@hN574`Z?Ww&goc9btP;J3Jf?nIBbxzyfz#h{PVvL8VYbH$kmAv_y+Hxtt1Qo zYm6fVxInU%QImm#YfQ#`v_J-~X)Tqt)!^X#nc(0;BjMogfm@+_aByBcaBv6aaByN- zaB!qZwQt?x4FVLpn&pw^xpawPp|N)#W3YnCMjr}GihAKMmxKH`z|Gx*`2SPB#wyDp+q?p4g|-b zjE4#DS<>dyaU(Sm=zHSva2+4*#GKUfTc?bzarUYArYGp(uJA(oY0 zdq(1@XEXpe6tDPMm`?s_0~SzK-*fvJH)wD8`lMxc1lQ)nHObf6ksFuC>(j^S;M282 z1YAQ$)(HYjtPuzU0-iGKM{O4bcSmRJzc5E*YB=KCfK&HrX9h$BB!n^|xJ5{w7iC2> zDjg#jtX=y_wzx$ReAi5Kn@RK7cI;Z0C}i}htnb^hO6KnH3zpjZaVO zLTKi`xD_VPmghlKjz!DK2nI!d6oERNxgto1dbkkYj-H~Mt--yVdBu3pGALJm)Q-Nn zp)Mm@_ou>%WbTbb_zK1|`W)H6G!~6H7MrGAw0d0pRS_I@^K2`9Hh}vTU6#`MYyXBK zrL-aJq3JH@WaNkl%(_5S%eTu=fIf} znxJdkK3+Rd3VNUL~)^(6Mo3@egkJU|O1WtjEHP zcuX@6l!GLhH@cXmVX=4~i4#$Q#uyRaP%lW$EB*A#iyAoA9mkeqQ531D^xO8VQ7Qwv z5wjiR8A2)EXMfT^k}U9G`>*o~MXuECk*?=HYsQq}s?qr{93SyA}%<|#)0O^H{yc9jiQ z>6a5mYDNaGR;e^u%&?D5>IEbuBw5+nqG$Zl7yPwkjsKUcFVDA^71B={D2In3?`o0X zASk1Ag%+Pt+fwO1xgS#bnVQGt4H|a)kXephP+5ZERIj{b%;Cn1jLE5Dms#BAZ4BtfO7%Bs9FT`6*(s1X)bBwXZey1kK_mOF$aUPh-Hwwv^qD&`nTD=#HW9=ph!wUaM^ia^Oo85JN1 z1q0^&_Xlicyjan4s#=;x1}1VvcP-jqSk!gV?W^!*i&~f__&if+8GH}r25H~0CC<@( zu0o1>W9O*Mnq5#JdZyC%Q=ReatRm*4^H*5rx5CG`zuCvX+5l zyfrhmk)VL*p-LvNt8eZUG8dt05;C;?Dr7D}#Yde;mNY^%OorC;{38jDRY4iMJPFXTxn`KyNC|L|i3*Zpyp<_T74 z+U*9bNNDkOZ5*M6&t~{M>g1#_g-YwWs7=D?2hrRWErDePzC~)xC-6N~_8h-F!t(HF zo}8JUEj-|tl$@BH#G2R9x$HFY*OBz^;R2=bND2;5P6|MB2!8pphMQ0O;`$PNZV-7} zM(Q>l6Wr&;Qi~7XN~nZH7UkfA;su4!P7nTCd!*B(KYDGLMOo4FQL&{fS89F>!6fRc zexrvLMt}L3hG(xnUS6J^lS6-KQz|Co z5L+D?K;172hMq0bmzk$Quh6J;UwfjBH+^Bbd1KG4UCiD;F>0B>`&shGJ_3R(wrpip zIEh^)KEn7M4^@KOG;sL#t;l<+p%L9IEaQ26+-Igm{0hZ{X}T@iW`82k8U{i|plA}^ zaL|ZwX>{`hyg#%vqav6_>`el%K}6bL#9%BJDVuiRR_-Z=S_Bmj9XYr--S^L}>$o@@ zo0=vM4%ig5G>MSGtcy!a0dr*+ zIcZb0?|Vq7Dum&D9j&q9AhsMkI0XD}C12z4{E^j-b z7T!QPwvn;Uv!%6P-{W}^f)rk=y`@qqJ0n?{go5vXSjKN5!Os?W|ZLdJ+3NK+oDHlYgV?ntPU#{NgM5)zJe@~d?kF- z{QLMhA3Hny+jcj2N6z}5YYI|sQ>%vFX%XDc$lH!I?NXyuCRQK~tym!|bSi|Ai^{U> zLw?C_f1+?f`MRffEgQF28Q69u$j?G6x52T=K}VKS+P^-3S^uIwQG75(s^C`Q!KM3g zoBlG^B&#A5GCOOOv#MA3m*o}v*8zLFC6V-pR(J|=Pt?u)&7NH* z-R^1DMUQ1fo?@)_D>89KpWQ|xuOo5C!WMJntBa)Z!UwbNeV8K6C8(RbyC)Z_4LaO5 z5e({0t=-)}4G$}1WM&Qpv2%)HW2v>xm*v`6<#VVKm$DjxKMqWomt5g@V}4zHysv-p z4^VIYuR*CF9u2w6?1@je(VL~P6oM=nQU1J&m<@f$Ga?#Knxf0@-@|HCZnNCj(9ap* zVzHT#&%tqI1)a`U)zEm|qR0x$*gIRX25BXXCCbo$GWyKcoGZ^<8apU*#&o$fYOVeW znlNgqpFu*NpyYdMNLk|%~TV~%<; zKE3X^HH5yWf(%Ne5avTolkZgql(v@W;_vQ@pID;iWQdp}i@t{KYwA4=#{a?o<4mS- z$<|v?|A>OL9+oEd0h3+Kgk8h)$5R@WdZR3(;B2Kd0+|d8? zQh>kNWAb=;WNnfI6H|P-)wz!3WEewQZN5n9i;>WWA0(RT7Fycm7*YE1!y+^0&WRJ5 zX4_jk@o#;v^tcK_(&IC^o7>x!3rK;cBe*X)NeaOz)!|hN<|{>1Yes4(3c9C7*C+je z;Q!M5F*ynMWscjA(JD(Q6@D`3jcZkbUjY;=W=M<<55dM3y4({W9E0;}t98|Nd(qfs zXVKVI!KVq1VODTv1?)+(J`W-F{{coB%6XT-cv+U{j)e*&ZP(yc*&$FW-ov&SO@r^O z>)v*ZkDp`2FJ%}Sb%IUNFVoHjOf)LtE~o$0yq+ibgA_-~Gj-WvY z7~{jS%ZT8Qpydz!GAE=;^v9ztaj65N4ECYoBG4fzo83HE_DTBQ8s}kiVg%lb60frA zjztl95p0#otHhFo7juw9MW>OL1{grF>1`+U_0+w{>7N447tNEd8`Fc+ua17Tq~6{6 zwE|Zszq@_`&$-&>TCsYZa$q&@VF5;5U!aDw&(Rke7%(yf;TsXJH+MD--Wix~K9;HE zNqXcMn2OGnsbrERD1Kr4ga`h_#QJ1f$e{w#P6TUvrsJuu(1aZ56gtez{nsD#Ro;H@ zd;F;Mp{k&6Tis=UQo<}FnT=aS{q&_? z06^`Ds@BVGt9koEVJW*wQrzK7eRvlB1D$R&k(YMqMX5aKcvL78RV!*gWZyX}*X7}s zB$=WFn122_a;4XgOPg08D)p$70W{hTt^MubWjo2TW-^P$bs0fF9)5ng4C~41=_a33 zQV{Ze#l{3-G!Uvbb=>LbIA=*#NhjpG`)%>}65U#$pc zWMuf>?HGszTw`(fT+%OP)@`Gs$o#H}I4S)S-JzXR?$t&27+m%DyO`9~eg^vg)kVkA z`ryY@l`{SdJT`Y73a}0ejh`i%fnINI)sML-u=KI#a$}JAzwF*K@o^u0!^gG^FYI}f8! zx>6CLMCvt&z`ut&Tm5?zQP`jBRafYbO*twF-;X^$N7kc*IQLJ%<|tK*aN6*c&WXEB zLp&yUM@bh=R{Qq^wi<=IzX+K{Z_Y(CG7VTJsLUFvG_zFRBGwl~rj{ zXSscMhsPhx{}00BGy;#d*B>-1A*7SG?=8QNB5%V!cC+woOR!wjDwLt?%+DV!cl4Y1 zQ12{D`gly#wjrPT)18e(gNfi5)}+KFuEY3nPuxm2KU^&UL0)Y4zoOvI5BOxOk-zoR zW5)e19rJGqeiZwmv;Uxu&K^di--0u;Cn%@58e>_^pnBmjuIuil46Q%YPS^U+w$s^Q za(da7)DPGQ!QW@o?>aduDMW@t!#*naalH;aUuTuaq@5ZTT!-$ydWdbve!O z>NH9_tC$u)Wz+5ZKEJK+^)0_d$S&4WW+rQOB(oMpe%T&FnVFghTgLh-2%4{nd=N58u6 zYl`jS{(JKSLbl~Ie;nmBMT~~&n1Y6ly*5nz6-0LrQ@HPN{_6n}3w)Hd5pK{Ll@@sGGn10sIJsUA62pG*R`goEcO? zo$WNf9X2i`g(k||%Pr6Z+)j5?#nqogeYBt$kj;ip9%n(5f*yQ-ADWKl`%rKGc}84o zg_3x$HRT4^$DD;Xb)GD%lP8Z}{WhRiRV;;!pU-)z7fKCP>dc&Psc<8I{xck}T$xo^ zXzAdPqh2Amxc|{kEysF~?Nch>o{(osH#D{I(drQY$3Ft$(QRZ@>Ylg0tg3b1xu%pe zKJQ%~KN%JoRy5IKsE5;PYd&JV^!N3ifL~oc+z+_aRyN)!IvGVo>KJh_7Q?o3@;a=8 zTSLF(nAcoyyZcqR3pR&6xM6b>+#V;Bn0cZ>(T*w;%C)m#AcC`#Ay<2#}PIW&noPjD)~^V3Oe6_w5}e!Lj9q_dYfvrNuksmW^A!U#VAiq zA}+{(r|g1V*8s@(>RViAp!;A}O%`@51-pv+xF;X8BcpAeNH-Htxs0ZzMq}vc(w>pk zpveh^t#3!7(z!33{)uLQ3mcFrdw`2Qvyi2~XE>1OpU=11cn(?%n&HJc+L#GjqWRk& z7U5}I-hbE6XNNAt!{r`P+#H6#XGIQIZ{n9ost!QQHnZ=^9aJ>rS;Ftr{OQ%cni{X9 zphDY5NouJwi@7knC#1Aa>yL1f((Sjj-2HPCc->3`Z?J+ z1Iu8^(9G1DhnioQe`vGB=l$N91n}?)VR*>i+ekvT`Z8LztZ5yKxiP@)o z++LsVjcS*vC@V)ywjKg4}w2nZ}y%UIE4L$y;}76%YBxlFbu zm=j?wK1|AZ#$RTYNy7LYj1ZqV+{nD7&XPvpMt zpO#T-AAU)R>D(QPHU$QM)fKEgN{~U*JI=(VjR8hanf>uZ{C>r#<6*@aV>FqzRR!fJ zL7AGR(%oG1<(hAaExynQQ#y<*iXd0ID*aHrG;2ospDFVDopJST*o)v`17;Lsz2{aV zZ6X=trq9N3EOAXXC`=)XY31r}TRk5#dZz+Dr$!2ZBD~&T`A>agbRf++rHe$HM?!iP zN`wFny3MiF(Z*AVfjzU-x-T{fQCol`v{M*nJp&~D^QpzXouF4SxE|1apZAx0S}uLZ zLc49Q%=0+_EmJGQhMXQJjfRCt$ZKc@-5SQs3%Dazr;?uDZ?+|?!zD`|wX57yyBh0! zMNsy=DM4Uj@IBL@OyvKi~;`8R@%UFk9`DBFjt1Zr~ev52hx9KLx0dO(fqSCj zgh)P(J|}ECxpNumfa1}VA-kqY&Q7;?b+63Ge$)4!5D}040qrf=J_Rg5GSCNF5DpOn z>7=E3)xTxI-@RvFkV-tgN!N5^56jo4U}!0LgGazoMkue)M{2G0;&iml&dUCSTeul3 zoN@(Al?Q1(24Btf2|GdgqTpLAi0CnjHF7E^ru-w19h~g@;;-~-{E?+Xlzh`Dg~6o$ z57Q#|{6PS>_DiTQQ7#78{WR$2{gMgr51&ercykq{<2<}#Q; zsFrw|a zA>FTA$m$B#bspLq)Wv2jP_Z|k(1MCnE$ z{cKzl3-4mezhswVu&@juicYr+ts5Frb?F(B(_m+Pb%`I>=~tR)I3IEEFB5yb*A(6RaNC4$FK-}9pRyd8nYcY zb0{!U7*mXF!^&rtR7EDS7d!n^O=;(zEaXo|o`Y3AYdq4@jr#mH7$}|LbTY1pWcV9D zyil)_T+Il3qKK)u;W;JsD4|Dzt<(lG{l>mbg1ltgHY`V5kEz7H6HwRBP;g#}edBCf zAHR-5o?{r$yZ!-C8=i)5OUp_VC4 z@Be(D8C(zl_?Hnh*y_BB6L?udW4{Xbk6IkLu?gHFEIb2vwgs-sH?zBbrZ28RLHV0* z$|(#0#dP$$FFD|(BL)!_x5)#_Wm9hZCe|Ui7io~pNca#bN-ErdI}dtKA`O05Mo} zA^crig%QX{rwM*-1?P6?jC~SZyyc8wqMsN{TwbFPA}H9aaN6bf%J^AEcn?q+ISy8bMYt~tA*r&%WA0;P0kc#J zy0X7{-ih7?B&;AYzxm$q2IOdR>ch)zk>_^5SxcjmvDg67{>T&yg2IX+)mb1^2DyFDhedWFm0!`|GrKUDBCy%>hj)I zg%-G2SGJE-;#J<+W!LY+!rO1mE0Xa41zR!jahvAGuV5+03X;*XIevdHc6fMb=m^kw zM?Kp(|K4$L(1WPkA2>`*OuJgvTJ+XB>sYr8j)@Q3PKWG{c~TxZI?NidwTl_pV>5Gy zFO0rqfamgU8U4Q1z>g7UlnG$y*<-M{ob=Ox==tNzd!~G}GeLAi`d3Il3y-`>961P%F0UlX^%|8lHDr-8ISqCiA1pf`NrFlC%iE3;N7__ ze+0T-sRj^)CQQ6HS$z;mzI5;P0`*kryRBK(;K+@8sWOOS{gNDpR=i;DlDMD7wuD7D zO_TPRurboq48Bar`ORja;SgpK#c{-Ugvbq@<@BN!8wn}^0r0_d`&K~3^H_Cmb3gkN zob*a^?I{ypeaO-)OBpD^mGwsR9_ zSj!xFavlqIMND;S+7`Tq3lrywZ~Xqh7XTEaoimr#a&|H@(1rBQ2VTdH1wQ?h_DiE$HE;_S$+XsZ0ikSxN zGk_8Z$(cR&#EUKWOj_dV8;MP2_I>`=-2HgY{9n z{mZrMi}wWF|Js}oao8qq$nxl?jxRXL-c8lj)f`-0+8K=E-ba6u#83X5be-<*&6ZG! zd44e!AcUs@X8fW^^Pr&qtvPzAX>hh{;L~CE*&t^3{kWg0R7ktYL;A0H@|X-cq$m+7VRR~Omq%ldNNluiXF^@i=D`H?L53je zKH=+zi8)OpMBlWJm-jk4Gni5#&jiui3YFc$_CkQM|K0J&UlQw}j)CQ&3wO>=3BNYg!xlZ0dh zU(6RiUsA5>R3?(#uHMoRyqrhSTrRG-W$CBc)trrPyTj>0vkD4!|8X75jh06neT6*% zH*=>qjY6UNT1212$N0K=In2y<=b|tre9jp(q%W{4)bqEFfHQ!*H~pah@Vv zb?cSo>(Y|eTIGh$3M5p@)DkQzRP@v)xa8>VTb*`@t}p6lqb7&D^(a7o)^B{BPc#>} zE0|i8YoFO+stRh-ShqsSS#Tl@)XArfEEU)(zaF)kcpbb5@(NOQ5aL90;6d~n)NQ0U z*1IxRLzJfoPT9q)I0476}Q3mhT5jQ{G$;nw#?NHk_Ge7 z_&EisspJg51`TvoLwYKnyZ8ISJsTJusGrlV&KI7YAx~xOXIYRa8~$ zXTgOvq^YTCFrD2%^kUFnT`C})R9$kkBhz&2+%c243>&oyPnme6=^e5wWu0^C=k#(N z&abhk0rPUf>|rKH28g+AAxq1a!gn58MCJ35E)|qgmiATFLe@{6?xh?Eo;v-c&{@aS zJO?MPCQMjoT3W*BHfN$IlY%SPNrkN(9nI+Z)=@y<3yXZ7lfh3~O3pM&;z0gcJO6VH z2b8TFQK-uYVjJPDmNi)pKy=yTmP#k~8Rm+uTk3kVXL`FSsTF7AaJlef= z_eSZ50b5O2zCiV_xTp^!LhAtu&AB$y!j(saiFG4Lx%>}mwQmU5a=&_cMEA_^e=J3x z7F8^n&3HP_)%%uvx{!GDt~#!BU4ciYQlt0UioF!QHx=KE|M~gddm>{@cZYX;zp|Ym z%9VSbT~_wtjUg?za`gQX#6QdBU>iL*Xs57gWFIAbyPMJ+0!`V_xjo&@x90fK5%7N5 za`f5x`8)l+5o<5e4}S9zu3NniCzdk>l6nslo3DU`P5CF}G)%w08@HY=5FLVTkNQ2| zK@E+JzR`V8;jzYBB?hG%#z;%v70d)*o3)9!I?#-B>*{ph8dv|Rdcp!=ZrOj1Szij3X* z4ypX+`8;kV;B`!8-KL!{rrib`u}Q8gXF^J3uKs@nR>-Di$X9WBKNHZ;9idnrmtPH9 zOr0doqrh6W5sE~HXsWmRPMY!c`JL@>g$l64JWx1^s0}t&X`eAw!(wviJ~*lGW3{q0 zj)W1c`L8-Z?j=97xQ0BeiU!{Dv>kOs38;OKu}o247W~}8bm;Smy3V9)B-U2r?6R$J z_wN|t+ip+tO5%%V4^Qz|rHh_(2@Gl<`4YZ9KcBt?2aL4+!MT}1!GZviDzW)@CKlkqBy_Dye^P* z4`(iTWHSTiF_F7RR>cy0qfxzTwH)te+(4?5_v@B%1W=P@f0CO~gKbYWb40cW)1I-6 zR*0W)nB<3}amuyxcc9-j)6CWDBJW8nZA^HHVONpMlMM23iA9B9A_dfh{Eju)V26%X z^6x)c*y-Q8f8#;uxe89TTxUSU|Ah>3Zqm^Uu#%uoCA}*TnEfd%aJr+P@WF8{er#s7 z=5L9cYf9{gUKFtXIiQtNwc0S|jLB(59tSpt;5va>o|y^~(VnMlhbUt%xH!D36fxiv za5)>Xlf!BGuF?(XGX|goy2rUDUEZ*A;htFG?oDio+x{mii8FtI<_EJW4wKn}Q%dFP zQ?3^{@lz#`K`qC%rY|oAMo&aXj5n_FMo*-`eH-;@n@JKhmI;+>M;v~p zZr4YcfmdVo=eL&07eE`&Pl2^>L!KW@iuYH+eIC|9aaOEiEC^5ggi^b@Mn_XEg7$ph z80VeN>A0ps^RTVv^~^B5rn}?1ApShD_f*^81@eix`INi1!&HI9)bm`z!>Ku#n;4wq z7@`Jw*YjGaKmDU1t)g^*>r?qu@Kn7<+*L90sn0uXrt0gy8o`Ez8-dfOzdz+uGm?J> zJg&`3Hr`YIq}}}=_-Xp>sA>ZtLFaK zFP_bWz@DVW2+pibj1%_>ms*( zjVw1+YkHg24L>`?HBp2#8zXp7vBwvYym}0E`@t6Vk&ojn)?61dPNLu^*9Q^Em~BVj zcy7-dekek4tvYc1Qc8IoG3NJpdoK((9~q|6gI00=#m8o-)rT-Zt0z-EV(gPUN!YS3 zGA1!WqjK4*LpVIbF}3i$8WZ|6(~VpOdcHa;q;_>`^p1(7=&pmg1v_Ma;JWS6>BERE zS3V2?ml2**#I1Zqm_N~YfV+}4{Yo=j!2dVNf5-6Lzj z*h%u6Q*U9k@Z~OK6E;d?>3%0x#}Yo;HFw35=AJ7vW`OCMrY*DfvotDbs%kM>BvtbF zZrnzdeHiov#JS1VIB$0c~w5!RvVchtRk@0xAeyBYA!bzrIBLY(?t7cNsN0QFV}7Cf+x|1AYs`q z5xi#do#3fO&4KHp&8?}QknYu0Z9(E-Mq1)=T<%H7g`sUM%B*_i_&P*oactS+u=a5| zxhK`9`{@-hfP8Qk_l7H&b&G7t5KwVMtUXj&5)Ix$Dtvi_iuj!~tOwYXSAf!(j=i(; zv$1Q-##7I4p8w#kT=W4(qF}=8b!wur7R_r(Y&1 zH*VjMsZ>S!*BQm+GNPNJ)tU5+&u;|hDD~Yc6a??u*O?dtHYQWvsREd96D{;cVUKbEW>@$2` zIz-;2CWtBdjyYb8#&#%x&7stiw`UV~v&Ta^Kp*~rHzQDD#3%wR07;=suNnQb72PxT zse6}gqlx7}^onAVnGHJjfJgX=Gc_Vtl|+8(jldEpm1vtvfwwMrNoLKEqM31?S5)uE z+Up`usx|?O&c6Y-zrNhyFo;P|ior9wap@i?XbHR}BUZpKNZd08U70Fqy|Ly?W0^WJ zzCKH8>&y3%exyF>IW;XWzX!}_BZesse}51Go@f2c%)70U1Jg`!PYFd)Ho^i6GHqFN%p~w40v3EN?Ep@ zV$URqMX2q2lwLUk{Nm=(BFR_xuDma4P&L=vzQrLa3#G0~gv_7Bn^qx`b3Z93OoaM* zr-y{uMT)$~F1Yqy^`@3N*IZgF(2e$-tHp_hgFO)XjXZ{Y|CH+wsA0Km2?{R(9O{iY zIpXgcZ5RE$RF!~tdS?8@(;J!t!t958SS$)J{q+mw%3coH-&J;y@9M<%CRqcp);B{yqw#Y981JYQ)7hkHxW zMP^i>rduA#fl2j&SAbQAn;)crN{{z$MN{&&yjx~)-?wx#A~T-@=X z=U9y*NL#eP+8(=Gp$tdEEBxm{v{ak+=GleRWY4PdvFm5el9avbtVIS}AH;&Ov zc>=^njc(|uA5?r}EDRC#yBLIw<}2W0wa=js%$oFjj+zhLS25cfs}GFQk}97+<`Wd0 z`guw8Y#LiT6+dOt(yHm4 zbU>-8{rBjSs6>Go$Ix-sXfvv464M`~sI{9Hc+C*w&dNf;< zG0k>IvA8j=#RA%uKa^ZV#sr1`C?NY2Y5AQxWVY?D-+?rp!j*KZN3-w7#7v@yH>1Vyh3blhG}xA1+@6s>8VAW3W#E{m!Q2R>%@--pGAvq%V3-6A*H0VKM}a+ zbw0hRU8fzWbVw1iXmpIRX|%{9Gh15(8Z;r%+#z@F(|J-ub^`Al9OAM8C+m|bUI<25 zTDZW}?d0jBcRcq0^aI142N5QsVJ$!W``e{@ZbY}6-#!=9K0Wc4N<((0Ipu%-lJLR- z8QKCoQi2aP6&rmW0wa}p-r@Gx-%^M^JPb>^E=r>Z&8>I~#1#qQ{8o-fZ8RmMb;aw^ z>%Ci#DpVmbF=$Q2v~Df7x729wz_TIn3~HIJUp=Oeq@_t_WrzDf-)tBqEMqxmUk{lT z-ruOz|5oJynzFiD5x9vh@l`8|zhUUSb7mAuP!!_*WtVfW+Junm^rm~=r7d2!>Ev_3 zq2rW{z)UQ=PwuvdTJ`FRW~EGw5}VWk9+NSy@CC=Mg|E=t21T@$7>BoBDU4d!Gl-5( z<}7hMb4&Z4Jl3&|869_`C+(Kpr~aejzB3w+A`dsG%pij368sS|-JP8MyzN1Nu(_&r zg_Utjj&yiHKWg(yOKbFP$kB#ReZ`>&eZIU5+qnN(Vd|tY|Bo7y`hW|}ZoLpjGD|X? z7=XJ=fg<~?xr^gUUgEj>&*uUrJMpJryhjm7Ifc5x&o7S`GZ)`qC!Z}_Cc7W}WCc8p z`%LKI@Aq$XL3_f7Ed5O+WkL@zjtuAGKb9LdO=zIox!cz6+bjC|ovD&XXUzXw*!L|kn1S^t+otg;n% zuwfy#)ei)gGKy4+;0gIR?X)QhXkbgNH}-0V{$)gfrwv*MFm9VMG`qh~{jyBNeKxyo zB`9PBMYnri(-VFW3gV6u8tIXuV(@VuhUjnrRjJ-#}Ik z!|Xf5lmewt93`U1d)ArujL*#xczAepUvau_nw$m;Dg65$?~p_)_VGrpZAi_ z318+l&iWB?BYEGNTYCw1=iy-WyNUd*bPbH3k-S$ZxVvrxc2uJBF(+r7t5>AyABi!u z@^iO^gD-@Qy8lrLr|JJz1-e75t#_Pq$_I3Z1Ay5SAmi&_+5ijS^ZLe9z~lGTkVwF_ zu$^x$K&2N`P|BgA7y-Wl$m70$KPid$9WWSh_33v-CSLHC3t0Fmw?$OF9Yra@Z(UKY zU=!+x#54$9)~9}z!h>&8Zy+HC>#L{^-kO$XMd5k1v@~|q@oC@-ugr`@NUAigtOhmF zC&t}@VkGF0evkiFRgPsY=AL;_yhpyyTB}>N^ zH5MXM=93bD{ z-Y*sW#VmY5Fnd^85`i5xqrv}n!L1b_iD}cC;*jfk&A7gz_V7zDr3la5g=!(E^j+>& z6KHjz{LP6?G@F{+#k%vk%gn`N^i3}$>Mdfw{DQD(*DLlGk!tFI;ncyVThZ4hxE9bS ztJ7W(NO*LB$=Q#&&$aq6xwuW)Lihou)+2Laszd_c2XC%snFR^GM&yy+2{ii$n~-xpJ(wIzxLOPPeCAaa1>Y zg91RhvMv~T=;(&bAYgGQPwbB4<*x6MwD)m`nJf{-X`?sd6<|(XIMpj;{~EOmwYjUE z2`nE@`UkWw-=v>MrMF8cd;miiV6(wO;o#)l?1BFHEcY*X-N(+ZmJip?Sq|36A~YqT z>WiCmI};Mmx7!l;!`$y5_iYW$%!VjPZGu|9iICbHSIY^8%Xwh2Qip<_I7IBJC)JQW z*Vt)(|E9NIyEJzlnF`!3i7?9hRJg_`jLwkyu$s%|o%(ddB=}ok!X0})Q%$yZM3#zG z&qP5{OCK&iu}akFkV0os-8c2}uKbXcvUy9Z-Jt$txTLHq$^}?z>!}U6ogJu0XHq-$ zXO-v44s(;#`pRnUEHF<*qJBWYG|*)Kvg#!5PQ~mR=+N?f6xVJQk>wBvyb&s)~q2MJN zUr}t;mlNizr>@X(SFKGntu@gn>~f{{Y>p}Lr?R^U*I74%)PtniN=oDz(>pL)aDxMr zciT-(+z+dgr5byMnQ)E6pjN{o=(}39EG>f>(J^ydeQwU}hPyEUzdJf7k9n`t7SGt#V45ywXs56)LAtMusvu4u3bUo{nHN zk?x;OT4%8?WDH@d+IL$Gswo0l4`>dj&lJjORsKH_%<@}f=UB?Z-6ycS{tD~2+d!fh zDI7VA*?c7_3lQ;9N-?%oWj|DnIvpMu{!DAHuRNBIx$&vXnW|$Gvm950%d%!Qa_mN% zNCds<&aL+%Yz4N~@e&np4qsC3QDW+1R@T z%9$Gz)7uc&Evo~IFa_+mqo?A@;8V9T+#d+Gr~{DU3j3w0JEPd9qc*2|(@$}>32}3Y zNc32YD$|nvvG4tFdk#hj7&4;ffxXLe8=I{Bf;#EG#tfIXA?LQ=1_%q)5`DIrd z)Nkd>sl>vlH-j2}k!+pz!opC40h%!A*sP_(!x+{E6Q(*1d3kv8l%RgmO+f;;2}EDD z=mCuJw6BECQk}^^+}J*L4H1vQr77o70nF`S);WPP4ltLgZ#r|~EyfG5R-6Z@ths;h zvIM5~tSC6IM&QY7<=BmU*>BoGKp*-U(E9DSWE zF_@|m7}e6ECzj8(+B(HADX!9%YLWPwTjlxbiM+Jl2}#6SdmVMD1sMYc$ z3-|^}F5DViw3M((Y4@pxI#ATf-*?#Cu9oWO1}%Z)GHT@+>BAKNzZbwX_0KHTOXn{# zqsQL%x6G67tCYF`EG!|-mba@KAV_X=tlz73ZRZ+a&>Ol4KA3LIkJWk!chDR+!+wVd z1-87>qIFqzBO|QequcBr(mzt*rGO7#y;&dlSNRJAPXk2X|3w2=Ht3EU0VYULirfAi zBlXiGsqazasL0Lugs12Dwr=g!s=OmE+?o2I(Le6B{gkO&bGTF0hNaifV{dpe98}@kMqwGp>H}e5hdJj@g0%pJ zGr|}33Y}wP?n8`#bIs%%OUvIUyTcM%7Pvq4PNExCFIDk2V5V@ntxL`a@dgO}w*_E( zv3vlcTbl-cW8?uxyX*habXH+;HO&^rT?Th|4em~GcXxM7g1ZHGcMlLC1b2tv?he6% z2OIqCeCPQuxPiG~y7%s?TJ^5#XUC7TyQS!%?0x!zNF*3g@Bj_<+p2GFj6*K{dd6UT zOcV_N9z^z-L}nHc&~2WJ6zg#-Ktdg&L8pB6?*Dd^%NLNFc5rGbP{O+jP|?v`qhbJ|7j_C3^+~jsPjcM9Lx&*S?q569bn(LGsK-^seU7ZYgGQY&EtSrJ? zteWfIwKYN&;XCZW>t9qtkBfCze-!G-b4%vWgKqdJPBhIc$uXIUjGx`dkzD6ctmYuf zx1N^RWV0GgoLDU$l?9hvaFxoqu_B)*zs>5t4&v02swCm%z?i3a90neU79I}|AF4IA zO5?o+-fwYk{M-}5@~^fJCsF>BTSSz-@d*o7HVn?veV%-QI?0O5!u#yn-|sTd_h?#* zGf?QpaNCy`wY0J$|}S^`Q$=mZc@f*d(=>hO{kERDhuu($&MgmE$ceEn&p*cT2HU`d0%#;iB>H zv5DCYtS%C!xx<#ZBMN$+^-`gW#*UB%5(9N*4QGHD?-uHn$4} zOt#^!!bHJv&Z_?CZ_XUakU^zce7F2|1u|y8nJstE4@wPbp`a%i|9*c(#S5CZshD(c z&-(U3UZe6JKT0c$XwU;YWB>sZ_?KEv=Guz+q*a=b%D8FiXpPv;uuEmDmfQeKZQ#TG zeK33c({Gq;rBgYwaHr(@0AG;?t!x!FrskGch(8+dvii;8@(-z&UCp1`45jgoSVJd!qx)Lo!8Pz0uOS@g{zLm+SL?tm=gt}WHz~O za7(pDG5j8fTB^&8zGWffzIblw zkgpHDF-nR!C^@P?W_+VHbbNejf7HvrtoLD_>ma6|d^Sh1PI;KLcTej;+CU$6N~^C} zB!h#*=e6|$%&(AF!RDJy*Cz%DLHe~c9x;;Tl?l5>MxnT2B(P2Q8ywREj&UId#G0PJai8tEB^MQvVH}pe_oe9=M`@@C;~coJ>U~a^ zrwP4M!W8;DBMH9ne21JCeGnpyi}2=4`^ixif!mO`T?4@ENa z`th^5vi#EI*KS1FHa-XOwhvN7K73Q2@6b%=GQ$0Gi*u}iLY!>coU<0nEt7smxn9toorEI#CNWc z^`R-*x}o5D$Im^Noi)G7aWQ1z6Oas@*7d}nueX%UX$-$Hp@|X0T-@np7uVIH%MiQ4 zSWoB2?e3ZZB^`-eGM^-!`>D`jriHW5<3UD8YLD~Kw(v2yLG+nZiGGbsY1WZv)|QJ+ zNGR65EtYeN5BlHkYJb-a_UVe}Qc`71!+c{}a*#&1;mgl5u&boxO*K~&(`ky*d-mp3eZ8SvE-sS&rl_JRKTPN)}viU1Gs z;be}@3z_2q`mic%+S_DH&+B>Zj!MhkyC0d!`_nRa(?;bO87b*-Jc-~BuUT_Lw^baz zhfa@r*Ify&8c{F&kKaaz1AgveW za`Wi$zJ@}m;S=O&oT9R(ee&2MN5O~)c0+Hv(~cF>(M^5tdM^r_pZ;UFcTJNhy4I>F5Z!7terY ze_i|G8Ju-v>uT%k5=!nG?>{t1fdbec1{05hDm%$yZ};}I-+;J9(*GvM6lC(^WNL@#lUpFHslIQR?hYOM0=CBu*gO=!)j)>_mGx&ZLyUXzG&|LYFiQlo?21gv$gj zT}+j8QclpVbko}A+&JdGdZ;8W#YssOid2_ho4||-G(&c4SMO%ofi8Jf| zfDkU@Xx*XDP*hV_!F1dJzdFC1XukkiEs&~-K34CZf4lv{oFPPhpQ`@_v75TltW(vj6{z5=zMXC-v-?Wn>GWc@ zEN#Fc`5?jY%?>8fKg{6e}M<34?P0Cw!Un!N2G9d8FsHC9rs&OA?=OsGfOT ztxm<<-48P@pAk^mKJ4GltBi!e-t_e<1zAPNH}3C~c!B#OuYV0B?9}jXvn}RKfTS?S z+*Tct)WxH47nxG{`C=n|dX;iA_}1Yjpkag{uqGy*p-Br3StMP9nU&U!x8w14NW!I} z(?FAPqq{Zq286msK4w^W(DIzY;&OJmeXT(goC~LS1Sk5jP1AY)Z|ye`c)@OY`%re- z`0T_ro7RM3Mb)tkGvVUL7i!f=PENgVFFt>WS2-K&>!^^I4dqMqkZLB|j@M+%5_%mc z{;p>&{bI%)Y?~IBv}?uf;oK`KMGZ$%&i>Rl@~bT=u_gj?X_kFvgDg}+#X}M+R5S6r z6wU25H8I=6k}=d~5VnoIQadXG5Q$9TLJCP`b}~t&d#^Li$S`p9 zsBC?GedJ{@bdHf-+jmijmfmQSLGFf7=uo+?dvYtTt8o8PhvU<8?s6#}NHz7nnwITh z=m*iDqkwx(guZ&)SxOi;LARk7sgf8p5YOGP_d?M{dWQ{MhPoa$LPzW6e#|(c%@tb@ zuzl=pmE?tn+s$D@9OjoWJIu}<^lo$~O2Q&kV|l+L=MwATiEnj+e$MIW@y6|1iplX+ z(=8RwZ2V?5sLj|ufn%jzDO`mFIgOVB$ripQwX76eld=-~;frK)MLAA(3-Zy*j`UoO zrdkSU^3%_bPjxT2f_dXE%gM9xe?wq-1I2D?PDG8aDiTX_5z!pO;me%TbQ-@{X{-g_ zYNu>usU?XA`Ib-#-Yn}&u)|F$a^}0i4JjVb<3rPlLc|c_X&OxJoIQB!6Wz9yH|>Vv z#Y_bb9^i@FvO&zKwmCw7QO7*+41Rf@m8QXl>?NSCp{(rdtcQkVG?0*x9x-9JzLGA( zL^Jj#Uo!E-STgy9ad?ZK>6XB4g%kp@F8YK3G~dWc178pqXzADkXC+W>@2OaacFZ8q zBIuE>c>|wYHoX>5UkYmW+fQqk#qlNNqV#LxM@JDA6&1x8;`S5xac$ma3Hbj0qQYQv z_+1o7F9(Y7I-TTo13Y$n03PwtzZfu*OCrN%$yqi}MHeF+&_|4Ul-fmbDHN4TfTT=u z!CK#o3%Qe-gD3v-#N7!^ujz*=mY|9oZDj8A@tCvW%H@qO4YTJxj^^KvzZN{&JH~Pj zsyQC^vVCc4JV`PUg3x5tf-wtXR#J0V5G0(Sw?$aW9%n2|DxKuXF$knR*RgZ9D23Q_ zTM9=2WyrHd$RpV$^EHqJ1}JXF=#LVTo}(dcltZeod2(&9&& zw@=O-Hgxg;phXHymK6v1NPWwT5-Dy~Ihj`D3b~EaqUQc6`7M4h^J;{p8`Hv;p_=m`#038luX1Bn5^%pVNkC$;cIQsip(Ogf4=h4=vY#2v?|HY5G%p0GQOo zbCuT3Bsa14p7&CR~tkJ@;qNbJ>Cbrro_iAI!-wnRFjyN z^6TCm(!KiJ2COxS$RDQA46qBnBqrOPLfUG;N)|!U{7C(9F?Zq@(4>X}9t!2jD1KqK z`R+7-TMfcAxDL1BU~<`zh;5l)5y%^Ve;aa!Jt<@=D@RxaQzaKOt$kYH$Kp$KnDme^ zUhie>Eq0a zUY5D*f_T1HbVe}Acp`CqI-y>EQzh5acFqd&VdzTgDGakV3}JNEN2W;*F@`X;u$1mw zDMSAQExrrzz9OEC-0l4>ITDm27opdq&WF7V-;3e$WfK{bcL?jdyO40{CZIs!B0}Bx zazwJ(dh09FzSF&Z<94UDe9VTDXk`t@FTfEyDor9>hBPJkKS+`-g(%>7==k>1HZn%VXAvaH-?uXk z=id1SZ^#0&CS>70CZ?{G314B6Z93IP3ScQxls8c8}_46v)l4ru1`G4FjiG?NV z>x&sM$sWuFwWOy0N{dh@RL@?vk|!i5>C%?_-B#owA*Ych2c4WEFEEP_7s|0bbI;vY zvscRBvuK$pFCiDV0rkYu(X8lN^c>5BLG+*^hiq&yBTuPwcuAcmQO;p&B`Br{jr$vp zkc>W@m}S+t5U?bugX_4C5gvgi{H-;{pXh8U|-cM!`P6_ zWVve85|+lckgdey+F8WQ9gwJQItg40vx~XDt%=1Dn}LcAD=8VJwD(#+qlc3}QF?4k z4z%-CRZcU{(uI;k^n#=#=1wk&Oi@DMLAl~V6www7_Mbanrv$;a>oW8ijJnKqc9lpJ|uMfbUw4S(Qg$tNAP?ap(=FK_#ic)lLX zc>V5+ytP8O0j003CUObiZ}^nC*4ya--%!7uft|CXi57+wO(*% zTBGSivZaa3rs{jShai)Dsq%yWiv#)dlHq8xx6?J}!)=$J8eR<-M^;wcJmaoinPPQ* z@(0dL-t9hzuICL0Cupnssx+R&=GvHKs`JSUGfA0ehdZtsw-n~)(APCyXo;3}SIg-k z;Yu3_W#p|oYy#8OLnPv2C!3<^{F$5FKCKtxVs6@**HQkoTMB27bh8?Ei|UPSQZG1tRR)=QVGFI? zK7UFk6LQaT;7usS+dZg^@Uu)btrNrfpV_H!7nD|v^VU6Rdi9IUZ`Q(mMP(@JHU8+NI ze9Y>1SX>spkS%*0AS*_zAz_P`S3&pj^~HdtC6`#I%RVfe4Fjd5-s8!8v$>20tVzEB55w;n`;@_D5_b^?AE_#A5I9 zo#~GBDqQk<&=?;!tYX=OXHoOrrMD9pVvrn#qD-R1*hRsWVRireL8@#fegR1@Y@|A& zUb;Xaggb_2I-%^a)X>p-pz^V|X7l{qeeMi+=;(g>hf8DidlNCXM_#BqW*JUz+~N;) zq^3~;+=+rnk10X)48y-TXFYzfsc8f@xh3k1X23WJuf3>|>-hqan4}~#&FZe>(^K&> zbt%iqQs=jk+TlQ8*OB7uwy#FAg*tA8WH{|i%{TbGNxu9t(`|Y4Blf>#2d$~P;M;sl zAHydk1R6cU;ewZ)SRda0NU=?^vCSj|AzO4O6XBZ-qRizZHxRh3e>ti}D!lJ;@2mHM zQTys%8Jidq?1Xn@7hxzDM(Mi8B9{(Pb#SLdL=Jl|_BG_*+c!<(o2dXD!~_48bq}kT zX_crD5&#PdntWN>UT7*QGedH%YPCy&VS=4w=8pd=RYXwv8Ts{l6D+SDR~v_hPkCH< z`%m$LDr+UVpqdq&qKg{YSXRxw19gI!4A#E0)dqGpwxIlc(%ZYcBK?};ISr{ML$|2; z-d>3G4<=|7Fn|WSo*XLQ6fNHtJ2N-)Rl()#%S|(@1U~-O{qNt@w6t`JLFN%_i;g_k zQwA<2+BqMy%K=%W$%iCP8d@*e{HO82uNgM!krCDEMK%th*aVR$gtpXke@KI(fh_4P zeo?%0+y?B<)*3m2mUq#L!8A-1XxZQW9Ecm+D|mGrX)f3iJ$Gw`HZ+r*rBR4qLp=6B zRW^}$GDv=aS&NN)u^BqP8|N_!7+Lz^{3VQx{tJr$JASmLe!F!as?iGkA7z4$@SgSV zq&^{Ny>yC6kFXHQFp5I#KX-8Uad3wd+2Qlc`4I}dh7lI={DfxMZOaeZjG5n-uNP8O zcI#!xhI}u3B7wSa)x)|(|6CkTKVvoT%V@)TA)M%C%0U1hE<{BdIP8jcYL&k1x2yJUNM1saodqJ7_W7 zFno1?e@!I^E1P$Z<*Ep~*BEukJw6?X==+b^7X4sv?ixP*1O`X4u}L!y^Y+dBr2d{1 z1FP0PCeLWlkmDAUJV$wbE;|VQJ837TQgQNuVTc`2AlTU0kUb73ht7iaj){(CTujJ- zU%DO_MHct;kO>P5XL38FHwe{eS1bRDLi<@ASNv`0Xv%{sV+~SKZl5lBxvZy2eeCt2 zi=Q4+Ri57^s=l6GQ4xQ5Y-I(1%jc9uF*eT3&m79aVjrJ`q;Cq))f|>t7woxX&`sfP zOhd_NU^haU)t_@#m*Kx`^uq93Ku+zf|6!jpw6bqkCsc&_8s(WOTe>o({X#>UZb z!#thmjbTUpi4Y5n6rD3gP}Nu`V@u_^WU%<=&=c;}{KPepqN|XnYbf_#>3A zMN-9uQ!jvzbzROA9rV5Ijo&)L2h z=L2m~Vu4RaB5fFbJ*3ecroj4!gl6asDxF9wN8D?TrAN5xizM5L^n3$72!kO+ye^?9 zvaNU?xTcdT7HUG6C$ z&;0|QUvb?Q$Va~}?QP<>J0=^fqhK)yxc8Saeyo?i8)TfXt z|LZSsfMWqb0je#1O_jlg+HvV$CZ?W#9n(Sg#42vjvcf(kZULJq;?!!b+lL2>i?dbT zAFdQ=!oNWi+1$uCc+7(@us7_$2PX0a@qo3e6?ibX$!#I3O>7CR#0;%OaIJ0=wJP0% zeO5*kFPXJffOvUG%HzDAjf%j5fh?xa{`+{l3LFtsR8+vzFf=m*Y7V@`09r&>djNCq zy6hYq8*92;o0plH`;k+Qjf>Bc7*cLM$fH8*((n9S$i$=StqnEy@Gb;d?24xuI#@TH zhmt?GZx&~BjXr~-fw*an`p=!uGs>p#u%?6aJP;#JxkImeKu~R|PMuH1Q7Y`ccyXc8 zU`z<7R3Z7;QNz(dZNGJsVOS2Pi<^!MA|%&6Q4zNKG%q)JVrMSG8U5XF+%mg=nOH~2 z{2vq8T&9Q>d2&qkbMB`2jlo06UbnlESAWWtROO3WD&QC8VJYKL(xsR-fLeAla}lV5 z6XoAeO_pJLPj-f z)Z7m$O&-S$n@Wd2nVKD^<&_E+H;XAONc9JT!6JsACiZd>W1fDX2;PR107>V3g#$V+ ztd1XzD5-11DBHzh*bq#it`asn8ChYId+_Fa*L#=WV#`S~`jhjm@gHK@Q-i{y!bTjP zV*ZXf>0IeY(UhGXR(^HdT=*ESI?XB|7!G}ZgPh0_C4(pPL5LUHLzviB!wCN$3y>v< zesefI0HD0=zW0vH$rV8t@9R0Cu@>dke+--)514i2&f}yBhX!ONE6{jn^kw>AJvmYt zX|Y8PgK85d45H;?-m{B}D9+ZJkb!SK0H73XA|mn2CV?b5JYDg-eVh0{jbNy-OO0@* zd;2nZMsf6UJ9F9DSjoMRsYjT<1nE6d+L5<9{N#f|O4N6#(B?M+vBI4yPs>+oa=iFf z|Ij^So+0ER$*hEumWnPyZ~Z*VV&lA3m-^`GH`)54!sm`{YW)JL)@o%Z)|H%^5T@QPBqVN2v$;YRh5~BUIS&Y+eBSxN| z_qBPi-cLz+x4KBViK`Jq#}=*H78=({9?msAB5ueO(gc>vYAFE= zam&13t2jTQoem|A9TE(*Dl;@y`^AG;0!#Lcwf1cdtE7(RW)hoyI7$4fhWYrg-PiYY z)Jw`@U3l8miAyTh{>6U11{<>;t8v$rU74LAoN>3_u{7OoKmNmstkC@Y{4QgaytOM| zU$Fkm&;#RiO?(K4)+M%TIEZEQp-WNh8?sml+W@o+g)|}-5ETf-OICA#rnwCpNhwZ14m&3Q(ys|r#_ZhS+ra=g(wI2**G$J% zP;(AhPPUN>hoU-zf z;TbiOj;FIqf}~Wv(MSCZ&R@Bd*!lURuCLwxou8YJczgYyPiNK*q&V%eC-OLL^Y+`0@<&*B1Mzym zkJEkpGKMuFtMGK=94(NKIie}$YoE}Q%g`{^whFL*+Bph@vVAfYl8Amzb9a+APUSe~ z8gRT5eoZEc?>~xJSFC#*S+CvI5(bgC zOhBpiqJvU`iYg4@Oa*kj(>pLy6ZqY>1GA5YROJ2ddQUcxYzT9j^5(ywym)tStGR+n zRQPWm+FZ!lR!~IUJ|F#WZdf8?dFWz5^L1pTWVMSc7AVBo9{T-jecty}bFP2$S7<;g*t;d0p$ zGJHvksSnun(cEJsv?B?DmWPz=@Z1kKdHVnW#YSFtWjej#KxqDz_L0_rsPO)$0~%H0 zu4tyF5$AA{Wfc4Hj0TzR8Uz#tXsF&z3tGnh$WO#-N@m0&`>{BIyd0Gx+MMn+ry@(^ zn}ZQFEMlWxH!c%7l=5tB&-}wlBmd)ak`==owH-Q`XGIVxPy5%Wn1|Z4L)*bG?zYof z%63*(DpV6$!tg*&Ka^!6g7vRw2K48nUo%)F4Ou(1TLZzpyn(dJTI`eC{BV}>&1LN{U+#O$f0X@^Zuq~Cc^g8t}#D8UVZI-~sO-X0`*Qw3HL4C0%? zeDRx2$%0ncQV0VxH1v7NnL^V^NBp#Obk|$Hm%BrFCWAySoxyMHOI*Bec2@E^k65h|VX0L@kW!k`o8%=?biRfR16Mf4*|wxZ9A9)HMCzDTuIrp! zE4Vnu6dJj z9<+0Xd>HuFdSJRDvk03h)f|Tts}&LUEZCGbapIPrg~S)NrD9E9(I8&fF3o1Ce2M(d z3E3nC29@`AfV>wHzIL#Fgfw&jO&FUl*Od}Y_=RmEi_=E_xl^}H9ilX@u0*k3Yqdlf zN~>dRwQa0fK6^?F=IzlVpcsGdX?6X}>lQJ#Yb8fTU_d|T=JvvS{@dw`L#gTIw$2mE zyYb@@js!VE?3Y1c$i>xZhRJYsT~|cQwhwa8%MdbPt;umizs*)JADUKjZ4e6R%bG_c z7lMG1k@bOD3lfp)#rO&m7&rRC5)UoQR?+%4$?Z$2Ksq%9-2O6q6YYgl&dyTXt1|Q6 zbdO2~mQkd3GNLIV4?<9c;^g6o_GyUH=)R?S0pLf5c;O4ak7{AmN*F`zV`caTEiNPf zy{e?XD3jJ$(9r(hG{@+5d{mX%@{BsNph7+sSifLu>g zkFJy~0t<{VFFZ=T_m*tT@)G5T>_x1ls(=2bWuNnyz@R zC|kd=*!nK(Xudr4&0-m2U&4m^Hkz$~UYIMv^%X z$9#B0dcRe953?zFWN3C=KWy%lMUYK{X6y6@<1kwAumf&}-b}L$n5kQ7@|K+*^BEQ& z-cR!OG4g>@uDNq-!77z=%i2t)`hAR;us<(fsn3X#pSNJb>St!=zP{4iU7_m(wb!pc zU=T@nFyM_-yuH1buqJ5asr8o}ko0<~e~*GE^Tr3-1DS$0Xk-7_wnTX<5adN`b1d2)+k| z_Ypmtyzr6)5yG3JX-`Pk@~SNQ&kG`#A1h0i9=4$FelmNcanmFO#N-)EB1UYxUA;fz ze5%h;J>yWFlL*e6QbHWbABMUOkoS9;X5Jde(nZLdQeY0DWa=a1pRsx7gO=wYjDzEG z*$Tlk2E*oiA69@X3SLnRTAbY=7ul>^uk|6AvyB=Vy;x%}L^(x|LiokW1C>=EYi-*( zH$6_@Sy3bhiy#O8pdm`KS`pFpfO8Wm5?^30h$@>$$GFbm_33~zTi3f+-tU#jWJC(D zR;E&2dQK4(MzKdfe0%&yK?b z8O$cF?8a}s2J2l19e-2@6@wVQ*jRcM>>}(DU>p-XFf~iWaibL@w8InV{F&zWDqM>r zbLH%vE!m~yD%W*`6Q7)9)uE}vx>Yp(G9?DJOxsk-SNthYIpmegN%le~3DyyQVv(f9 zhhi=N8moAe$dflu(kPu>)~t@4SV>%&Ix|N9hajBuMyUz*HmPba#QVnWzU^q|d&BfF z`v`F;U>s~O{MY~%h860exr9G4-zoOEm}Dn$*?t$Q3b0ET+5A-`yI<0)tQ*XRvJQHI zVZ9p)EU&H=G-^rseUbV@mE-3Ji?0*4=<=G;+w+&M;G?o$6;sa8T9ta=2iBLfis`++ zNYcTCz!!@TdOrw*zti9jX8q6-WtVoO8)@z$;8kCZI4DXy!0h+NR5Urzc&Jh`=&MDy z$+pn@AmUXwk5Kd3MYQcXqH$QkX$xb57Co2hM__e*z1w#~Z*u3>3!mJ;KG;lQ8y;E* z?q5POWow~pgM4pC`zkyCIzzv%5a8h80Cq{0RR=VJ0g$01m!7k4o4xNJR<_`S0FFjs zgfq1x6ioo(bh&OMNrp7)ty{#>4vvPVpRd1}#lUUdNwn7@K_sL;3NeT%%!EEHk4`^3 z3AD532-Dq3Yc;PtyrfrY9=(>nj^Z8jq=5}Cs}J{8RtbFacb?DQjl7zD7BXaEvS9Y1Ks717FkBlZ>e*wNF52~jI+cN2J70%j;wORleo z4r`X#bIe6+l9br6RP&Q@)!ThIBK5(5V0Z(f2@+&nTXfKK%wlXh+o>`IQugVhjfw zZjyuQ_hM!81Ej~$6yD?-gRXT!vcII;DMIEE92YV^ykyQ50xKJjNW4#1#H-F(f@s_I z_D;wh9*|yGP?dnhgSxjwxKdyeM6darpZlCL@pF2MrDA5*mn|}diwN?z)})?2q2Dik z48N>ewF5cW>M0 zp)aQYl9pw6$2n*g%NE=F{a$Et-q4!W&jaJ)m}`ObGWGE?3XZzJw+Xva|K28Q-s)Lo zlM%&0;O#b`B^co_IV5WV(m$X}^z=8S>#~;S-c7ZiRoh)#au64bw1tubXo_&SO4kmx z54Iaz_F->ge!6${C@%((9nb;M|C=V`ymoE3K;E|gn^T{=rW_Ocs$$=4U6oDt=)A+j zC)7_D!myu2y{0sSHTriw5%1G7woi;L^$syZ(-obcZ7oecqm*}$ajM}UWYq+3+}=ac&HdalWAIo$<{!|fjYB~1wT1=0Y>9rcFaVCXFC#kLe{qy<8PvJg ze_9~}Vs|`{x?%u{vwMsnlH~2(?QR!8I4pQn4AHJ=qA5CJUno zVUx%&`=+#%c))TF83;`;fA-`ddqB{nIwHp4l>5l+T7`OM>3u&&i#^z(qm7oPH|UmJ zp{j2&6!5&?IKRC2@8pZ3%l~TM6usJD(?Kqo`#{MTw|251QXVK`>Re9UtINi_aq9mk zkL);aKyORk4rKr+Z%#b*8-@+PNmbs6Mz*6R-T8Q$D>c7f&>=05e&B#T7QsnLJxPv@ zibAAgQIvy@BPmUFa_^!3l2TsDj$fr2KxZA2fRX9!_i;JxNZQWF$Z3Bh zK_t5V+RfE^;Tnchy{TUS)?M%c9U*hvAVfUZ&EiTUx{p96z5E+5Q4P|Dul7rArb`q{ zlVeFA5=NmWYhcv_DrxwypA+XqL(81QiDd-I!2F;`54Usf<-I=+b;H1k5AdoX%nE9? znls<6Us{(?M?D}_-b%w>aMFrR%B zVLFRJM0IUDQbn$NbXlex5tzy`;2qkr^Gh{RL(eJv#PYYQc$uXsJ*_o?|LE}U99tyxy*x@o7nExF+h>Z>T~cSAwj2n;BL6{~ z(e0HP&`@=7dHoyD2O&@=Y7BN_^befcijvlKJbw-m5n)mFa*lZuzOgwS(q`}K_9A`H zjxM-#Wg$tXCk(~*ewjBTxaV@GMP`!|fw^YiTXHhf>0oslmK|F%s&&QC`lK4{WL0{2FyUwW?|Q@JI?lMCOv zjugV7&OPoaA6Dvq`>7_O|M7qvlRQo~(5=*jI)ai*Zk!}CV%pBW3RC+HBW$a2Q|+TJ z#>vqRM{JpTS9-ASL7!%DB#6(=T}BQwLQqib`HrKq`=ZA1M zr9Cv~sfgFk+P3}?iMP;XOk=^xw2jt{&(gUAS_V}C?(4wQDX@K>EnB?lI z5Ife{N&R((n!P>3oVd`qLh5G&lbbB@MFRNzb;fdF4fCCyormlkjC}BVZG3aosB?8-s)b{N97}YH%S!F?Ap92yt zllJ#sKWb}G%TE05(c}C0k+e18NmegbvSFnQ=r|tN{+ZkkA zK|pwIR&g_Z&*_VSK=)HzE9e6;2TcPW3Zssb(3Wx`1ueb=2H$VD>{1QJ_>)?@XuJ67 z`O97hT4xR|%CS1JG_EhLTa(})dS{`i17 z`1ZP@(`Krvc|{HQ^dS7NJ)GAaNDl+USug?(*%uTP zIYS)Z%>>LGU3n!(h)Z=f{?_`+|6=36y+a8Rq77A)%F#;FZathx!$3Gmt4-_*QQNxb zZs>PCq{|iBs?M>)k|)d$sL_@zneF`vD6qiIT>A?eD&e4hiq>ZzpX)97%iVjjt*8Q#8d!ziZOcFgUULteKNtBl=2ER{iE zO7XhaT>v)+$3PyA6V876jwiz+FAkckspNtxf_IlyM#6ptoR1S(;fz%-j1rv&Xk*No#^;$JLOi zQACgY-s56=hI*gLq*G&Gr}@cE`eoD?rxBeVpQv<>NNrcA4IoLsy}#dcFnK0a7JdEH zGOGG~_v*R*&tDrML-x!*EIk4W4;Ifo!h}3R2m#eQxpdNZEF6~-&ak(25J!g8K zIrSoXFxlsY+1A~NQ@1G^KR%GkG_jEQ8NW)S39872&GU*Pk|dS5G` zn*rPRCc>4YWLq|~yc|iRkWoDAXg<=MkegG{JQ^Kh+-ZNeOXlKpeuvjF3!Hk8_->>O zX$@%;KT)u-urh&pf~@Vwl(`;L{0Jcslh*Usv7#?ml70^z+e4BMqF;-O%tr2DDSFQj zE6q^3=^LifYOFtxb7&Ct5!jY&*>rA3bw@A|F--RBi9ZYd$jRA(BAn11lW&Xe{ERj~ z7rLaXYC3_xXlWNstza|+VO>jyB(YCQZuQHS@XNH%!QXl@MgSJ zg4RQlI~h|Qva$(Ed+h46gsoosB6w(XpdbU+5%lZKX zrQYk>oGV+&@Ai7++oFA<_r2qIqRLFk9g$kBSYd38+UB80v$_N~#fkAbCR}D^g_cZjUr4Wq^hB@;D@sFT@*hUFDgjAVp&MH;8 zVKByG(n6Wb>z)i36NAp~y|eW?UC74C&WA6D z%FaQbL81^5PWZ1Dr6mhFI%BasXL z3#PXLbkUc~s1bvI6c0xT01W*X(^{NK7}Mm5vV8#cu4Tg=IpEXuW+pL_%+OzZf>yUu zba4qB~U14Y+B256*`f-P<|@6o{{!18UQM9g)gLUvKn}8`78c3GK-GKlC`N@ju5qeDS|^utT=CP>fOrXLBpcce)&VA?R0GdL%@ z>r!VJ4hG)!x_~=%L*LEMt+#*2T?a8_3JqCRI@q5ZbhlB4T|}P|Zi{<5O}d_Y9@You zVT+af7AjD1kB&4n=Y=|h$Tq&kh{-{|=3imW!@8O{C0@YKD*HPJuzP*!$NgO!TC(N^ z?j|y2&-DD`2RbzsAlTdUjUH83d+)6vo}#XKi8Lkx9Ho5bi;TqY;U7%z{w$i#Waj1$ z4uZq3b5sw#HK@m{4LrQ8nCwK!Ilb;T3PSxuJyJlkBJ2l`>X@+}wrv0U;F6M(K-+zw zI2>8+ypj-aNNAw*@uuE!l|xY(Fhe~g_VFP=qJ~oFx49oExpX})wEzmZhtGGDp6Zi#t3<2~O>dEqI>@SyV;er>f(4O0$@rFm}KyZ-#OSlp?5T<{&2Q1`dZ&`*9rdK33VHdKn1TYcLSAL8zIn{^OM2AD<*!Na>)ykFPU|% zyMDYI#Q4xWxzG2duMh7}5dlvWpIS$U#-fuU5f-)F-bEWaZ3$1C$;q>m+q=N)!<6Oq zsm7*&9VT|Q$-D4x-)*~Cu|?ipq?c!)&6-^f?8?V3V^30?p%U$CenYXOG1&zX`}z5X zV+TlZzl;=wc?HaI$`2l(4ygCJv(I(^Q^|MxV<6FnKOz#i%}=jk6ncYCF-TkjT3(Pm z{}i|Pp<N!2TH+(lbnoZy}`)DGBg=pzyy^2yQHLCgl&jVCM;Ns_y)Yl5jnPA zJ%951qd`9zON)pVnNiP$x<1uB_AO0ng!swP(vg8&B)CA>22ELD_oHFJK^mXaxgAh8 z^~E|JE2kZPs`(u_I>1|B)cnZ}_fjW5z#t3iyc=re{=PjrFWf)R>hkm~FT|=I_F^0T z=}7076m$R9pR-FAgT0hio@VFGXfn~i^cQcln_iD)8SH8WjkbQypRQ^=BM|_<-tBuE zH|k!y5&C{ZvkN$R@C`pSG&sE6w@lBrF(}m!lL)*~x?eVKT%}79{ z<`{UAscxqkaQJ*M@k1<=CwT4h|Ef^$b{DfhT~qsh^mDIgH-d;ON{1^45e^EQ4CkfTo+5=rbLf4|^hb zdCyiW9~`?x7$;qFz7`#D_xq->iD#~==ivW)xPUo$!&=bjvr6G$7i{aSt(ggZoCsk7 z6rbGo|Iu^~&T+MGACIku8>_Lsv6IGZ)W){m*tTsvvCVdq#!i|vP8-{PPk%G-AFw++ zvuEye-PaeN?5rklEl>Np28+2 zW%M(KTxEa`Z(z(o`JKhazVl#SyNhhGZ|Rptl6om|~7h7|Esbjom0NoBfc zE1ftw?RGMbt)8W(a`57R3E%Ow4T7jKM2GAZjX_k_yq5#7_q)EE?;;3@ z5$v{ic0lY$W6~@u$DPBX$#r~*Lu`;aEFDFtVXlFlu%08BgSdG@DR7}}ebW9o_K_mL zExNpwv_rR2`?ORyx^$L1dp*C;&uXm|!Ti6({jAy*b;&Zdxt8;pJgY92Yn^g-k>dqExu-B~}~1SGaFt35j9B zBL&aE`Idd{F7VzImq*UZ+KWWqC98CiJWbP+TqVw+LH5AJ*eS7JYp~jun8@Lqe*ACG zI@)~vUe?f&ZNvLs-){4gV<*swjlTm+$8|4>ueZ&5{@=@s%jeta*niv+&g1gfTm`wA zmD~TsQ66pm5J0&=u+FCZi7kbHai2n$KeYLl;ArY(g#=s{Tys40_aQ>CXo@++hty`R ze6Xm&P(fIUdi)0eQJ*JLr6W2amo%VD4X>^muc{e;8^#hCMrTTRr)!hy zIfAW)<;p%!p&u^3{Bb+gr1Z4O@Z8Cnzh^U;R(yKzyHHW@d-H?MCDrHaw|}=1!2fsAMd#&t&!$Q+?l)rYGc`P_VA! zL_TjHTO5~STs<}}&e+WjcRYhUlBvFf1X!`6gko9HGJuY5iTp2P2rl^EPy4s?_%>xg z@H1qSVI1L+$RnQ8lo#FJBEQUh$nHeYWx0rIv)<`qsbE2H<)go_N0v32f4AHV!NzOd z;&2TTna6Nq4=#UhZ;>8WV80gt_i# zeawbdB@*qq&!1KjdikyS5<%+opro6>>XFxodU{y3)8jfdcxag$1VjlMqd3?da0>t$ z3Es>4<|}5;%YPZFtg=|fk<60=p-#FEKZ(R!KA&32>2W&1F{awlAd0vw3kk`9Ll8Yg z?3!I69pXPxW~;MZsoABPh0(b@=MCWLB7tn7jTb|J6kNcSn z2Xt~*Ul2Q~@&`7z{P@kz;G?su|4z@ZR%-nRzFRSMzGA2-)XMq3#PTJvyfbNgan(y} zC18ua&I7L0)FYQdVt2w4HC|<-FNk5`Z(Dzq#-lCfOVHxmv?~{FDaL;mr@VcspfEMK zGM+a3UkFur7(!c66FGv*NHKC@eQ*B%QuuK`r04zjB7mgeg+-Bq0=*A*Sp-h8yQlq< zKkuDLFWUOvtxNJn2K6NdIp6EnyRqOXr}&Raa^0u+|FynQTNkP`QpZ!hJn{8ICiymj zP@)$!&1xXejHoTXkMHvY#Q2LUV9@+E87#&ct6Sj8pg*t|%dCRlDy^gZp9PDqO7p0a z!sMq-#=Wep3Wjm_jC4%q+Es$oHVPus7vt)vr4TDUx4EJ`YNp$4T?ZaxyenqevrE4y zPdmMvF-rT^btk=UqE-|FSR#%dM-Uo=<6ClBTq3 z;9jcJ{FPb0R5SY#t+)kIPP+n;UGTnO0jx5YRl$Z#i%>whV!^TC6CQ)(JiNB3mD-Pe zIyhgPgP8lEV2_enF<`nj4bH0cb1RtVcF%|Aj<^fyRQXVPtYlAN_1W!j{)hEA13>f@ zjDvpZ*J%FbmO3!KyNV@Y^fQ?Tm?rg3+TY(EE`~81{GL7d?w8u~FehWz$U(UCXPz>| zo3Th&Dl2`^Eyt*-^5&Y=c&X#&^JS5>^@yORho=N zzwCC_JvYU1!&e-CaSqQkQK$Cx`JmDh0gY^a^Wi8QU8lnd+6E^jQYtdv23S380YKu*=ZBvf zDiXBV!i$U&%S3ys-tjHJq|!ekxJeN6?HdKRPi}qHvLRPPDb&J%m2g60&Gl&CEH({n zEVvy|m>APZCTrgsDw%B|(~-?8%E~&H84ymzfP1FmCV1zhj8EH6U zcBZc;K0gAr83FO{_wUcPK->gDxL0^8(p2TzIJ-igA*s9yRYD|j95Yj-eHGKrU+m&t z5T4pF#b2PW!?1OpztZNnHr%&a+=|L2+090ct@~T(1A&X|&!rFsW zZ8vPY3j1G$>>-g;Zg_r;Ok%hl)5oh@xg|iG5>S{8S)Erw+$E{+c|mCsa^>_7!O>c#9x4`#T@&4KfX!RTRfrbkjEZbvj|0%ICq}?$~|N9`gGC*_PmCaad z4pi94s|0jyV-7S3Z+IWG0DtTWupg(-82glsJOD~({uYh^JU~{UqT6BAEYfN-GVFQL z2+9SHuLIVl3Rbw%NW;P)=+7BMEtH+xO$=tL)xyUt&zekt^Ry5@f5`%eJ}s8K?GoQg z&d-GsZF-}gdvakYsKq6VdQ!bq7bDA3b$WF*!!ZkU}jS zyCYH^Yes#LjnsqU2Da!rrs0#d zx%J4-Aeg-f^-@VT(-Ztsh6@-n*J~E*0~s#n?yrIzTGX)f;&h;Jt*UM(K$6KHf&0N! zXmlUnx};C93Q)N^N+Y)u>UVI?j^k0-&8ufi9Zdze3lRaQAx!-H(B(>tH4f0+Vr*b* z?@E}vSMc9nngtTKE784(=o@CIqm|=#N+~1j;G%V=G_IqcSHIh~%DyOwxx3EI* zM;)o)#buqohuwIR83P!kMe6+hy1xGr@(h??7zFD&|7Q2gC-0g0sHS`zTv-ACQx=)( zI$&f;-BWEpPaTmD96W%4D>Ccv*OKlA-+PDe##XPDG|3jLe?z8Fngr*`PYFEArLA#5$JVu++A}|2qkdPxgLAM#nyQ+Now&v@8ds? zXT1xeXYJc-64lmxqx&4?kYqnHs)nL&u~^nCgLQsKDG_I}0Yd|(^_ zRFAcN{_JnQCRef{N*}34aZUOlP}CMv>r@SSNq2QliQirM{GUH+pT@xDe#?)e^lAdi zSP}0sb&jvc7^&?${D(e%c~8pcQN>7Q>Q%K}cd+-0T$Tl<%J+-+P!wywfQw(5&pjcO zh*r^j&w2(t?H|#uf4Y^Yy_*4Xt}Adt0*PaP@VeH!W6vc*wlxfK9wp0F{@+*V4p{8x zg9p*QzFF((xs8J#h>w>;*~R>Q;k>n;YYvIt@gL(7QQ24pU zhUf>jwjAs>n(zR5cz_a-91tl~ZFvjRh5%pVhaWUOmrt~47-!+-$JivC<8|K8KyBT> z`&!d(VF-p#@~XR@EigV7sXxB|^1Zhjuf8(4;M@P2(0k8cq1;Q}gF?TDPDOzdO%WU| zCI#cOXhk=>BBvOOVJ~NbJ^R~i<*{O37($x&pNW8t!_IEB8nq9PkK=!V9NIWP0x2{v z8KZsjUGGe5c?w=ffUk9}U#$=;CNy$|RH}X6&wb6eojQN^>mPxt_gz1}C?@Ddl2$9M zv%MK3%a++W7k!8S_ApEifyESx9Q+L>;bc-xw9i7f1}_XkQ@!)u^1mbGKAF-p%dfWW+))hswMM_MXI4}CT%zO~wqdS&=!jGvj4 z1E4PuC6Bo?@IOM8Ig~~8L37;64gW{k8hoo93T?o%v=u$hHiGzeGVKJkc$os`mI%Vd zPYggAGi903#2b%WlsF?^*I3Kikw-)`MnWogy2HV?if4(!J6zS5F{uJ~qtYDr&!0hY zGD(f=_a3GC$+`r6d=SN~sR@^BRIc%xLgaHuK8bpAE%uCzOni$B%fE?5RX zkJ<(t(zf*%u_Nof6)g6BkjXmSM`st6ppYw8*w{1*#y88WeZ+iKbiz1}3s>ZfXLOOk zN7BD25|RK%OVXsc)hO)S0Mw`FdJSRNiTVrTRYHu|`65_yc#9ltzP&$h zMsVTB94|o^g16>@^-OtpfHLKK!Fb4fIB}h4uL0W>)cxri;uL>f@15RP?>}ie0BH>M zztXJh_P$4!mp>7r!QE$FsJ;FP7!E3JyBpCOFf zk%%<&`d_tjh>9jy3Loos92Cb;lzqqazkoH_i=bYf6Dpu77q$nh#W#HfeX*5ZzESbs z#0u8<$iDk?A169!7`6JQSt)5D(=s@HZ{J;YG=}8032~6Ye#S~T?T+9@ii9N9u23^a zCDEMl?qmbDj7HgKNe=w?z%-IgWBC9bVWr8PDLrFUWl%SQitRwy9IYbHAEM;>P9pI9 z`kVAc+rYbwX&kyqv9OvEkb@9`M&uK7w&8zf1C}psh1Nt)%6A!_Zx;~{0S<2pzdhDY zGYvB((=9b}pe=tt+q9SBgQcRzj1$XBBy&-_0>{bpLGejZVG7lU)RN7loSB6mph@KR z$|D8EdXUOl5!m<4#SInshf^GC`<>=Vz zoc?j%w|{^6ufuSq$NSp&*F|&T`dLQ&wq|RjqZNY7^{W#8x4dP97>Zi zL}L`oh(|}GzzRA4W(p%y(%2$a=8k41x`RoPuNs0|XRavq3_YIB7E{)%8#U7=t*~yb z_tZ3q2wZtL6lkH}1MP&GdC3CoC!WTxNdQCe4_9Xt(*cqYQ`T&hKe`ylXk^}d#z;xVBk?H>{-*)}=oMtzU||fM)9x^MCQCL5+wGy& zRrGGx#5^p`<~69a`Mlv7P>1nez%(5E4_J2w*iJ7|V@s-S0B9&VP~m@lvDE&CuM8kC zx1h@K{yxF}?mzbb{ZfRvo30XozY41P@-@^VU8u4*Bx|0Q6$Sz>O*UH;9G2Q?cuYUm z`_@LxxEs6W`k$!~-3QwjnE~g_Llv~+3tFNn-z`CvCuDK5tw1#&M!uZpyJGWTr7)+` za*6D)71d*VaiyM>mexcO_p?byA1?pX<&9VX3B)xttzVK3^&I}o9gLe0Gm*^17O zwJ-!(ef9R#Q0f=WQrwvi$&$}FC3Sc<3vmRHj-?XRJT1G4_=#f@)~KW;x}?#Hz;n5F|7IQ!Q#>8VT_XnhxTUy*jZ-b1`Ym# z)9=M1gc=2!^KTQYnPi)8=FwF!lzy9CW=erVpWdFA`{ObF4u(5!m)L?i!a1kqI7i?( zw?`y$d(H+yr`EYI=fkb@|*F0Z%C{pRN8gt^V5CL(TD$ZH9k@wWB7_=3vd zAT*X1@uWXqCrRrM-P6B=*#a&VGSRdfJl6FVQjq!0()c?fB(0#6CWdvZ#fF23@rCVE zEdx2OCAvIaj zR+|cZjJ$>q6*;~Xf|JqCem%vAsZDgHmy4{GxFZQGCG4j9%&GRZxt&H>P_c9h9PAH%c%57H zaCE~T5z*wMI+Ljhq(rDr+aw`SQ_yG3E*N{A5vyGB29Q}MP$mz(3mN7re)Z&zZ_?1O z!*Wu~UOCIB6kI4{soVF8R%a;kg(lcJL2j?xpE}$~d@~?;ePGK0>D4V>NJKZ;(!$)y^>J`WdvI?20i$5^GM6 z=y$T-P4G{?RR&+e_3Yr)i}i~J)-Xl(3_R}VMaTljPKD?tGC&nKog5-E3kLLiAhSqw zc5L__QIIqIzW+DutNY^TI(mtVh@q=16sY*+{>$&Dj=(0gIBw7)wmKm_sue8vsyI=hI(}=DRjGIhLqVW`H)6^+&B4}RQtDbhiKPCN zZHXLy`5GI49DMvxK8VN;@Od8K!Mx_0*6o2(NnUe<9&h;${$!s2Iru}8Wi$$hxV0lr zEfp>_y#t-<(P>PZgT0$yWBEGoZC@HXvhba*kVy2s;Ql$#eN-9&5+vx*4GT~)ZudJ*+XUH{&x=M; z2C}nUt7gIkJE~3&g{DnfHz>GqiO~b(4!)^3IC`ca zUGI%h7YZjSaiJ$?NsE24A9lgWT)?*`bik z;zDx?YQ5(7=@iT2z;#nDWNyl88b15V6Z?ToMgPL>EAe*W`P3FHRZ={Gy4go`Gat_S z-s202-*wz18mj-0nQ~v!XCP|Ne9OKjyLXb%aRh+Ia_T?;}4mb4?M<_qEP| zr+JkCmG=ta&hy*)cbXCYYu!z}^z;n1WgMY*Ak2*J=tT`U>=4b-z$9Y^n7_iGzyH4% z;C|CnROD&4e+WSCupmL?3`U@*M%M&LiYciDK5FZlu1WRIsOi93j@C}upwfcm9pQ{y z!r^cN8)PHT>z6(yBdb-n|~@B zcFTK7O$ge3#o;-G8g(_%HK#G3aatP2)BZJp)Dj?+wPzCLf{?K+EI zUxWYnv6T#?As{<9bM>XXB$(P6HkijnfBCXcgGP;>U42<9@EbbN73P-PVTzcl{%|RL zj~y_)8DajN*w`Ukzu*ty)3qxwPs^S=-=UNBK!Id+lNTKr1@WmQ4fc#STsNOl)uzOl zvA!yzv@EUpFyWO1YWQw3k0!qe=ugBat87k|6Uzdzo3GF3+=5=y9dj^?3hrOr6IFOba3Kk_j%v3waSg}>hwcK z24)aPcy%>9Njyi^0{HFWwBxAyzeekM8Ez$5Q#5=8*MG#Ew>!r-g!kQJ!-#YuDuNbD zBE;>yn;QEvw_F$YFDs<;9W`o12=+8~JgUd#x0TAg8L_Ar!LpX32%=wLfhEO^WK2t34FF5lJkcV$VSbY^oYNj-O72sa;@yY(b+pf3j<$4B)y|hU5gC zE?fox^vLkil!#rqzc)l8|zZOy#}FX^PA_%Jz6PF!XjM13vF<1%sG+} zm=@uv57}#&foH4)BBk%vZtFQE?Il71hi~84**f)ZK$10APJp2=3m@!k|KftZm8#db(M^?E~;Rv{vnN?3R_k`2KV7vCx2$J>#OyNzRgag$tlHf zco>N}Ejv9wJ|f}YakN+U!i;OL(TWWi;Hgndrzw5=RU4hYEgIdC`mfsq~GHY{YnJ=Q`Lj4h4HFQYoXm@Ok6B~sthRYjzO{xFz7q1niYFQ zqteX2@ir&okYr)agtt>eCzOY?NHM`LUFZ~s_0C^>mtW^M!^-5wbLhR*%Jq7=>;QzZ z59alV*4$uI@Nur??jLRaxZZ$UZ5^@%iWkdeCWWtli#%tj0q>6$?#u5j{#OKs-x`_5 zv6qN67vUl>SpMx!fZ_KM@2ls!yYpLm22JkV!^4P3IA*|wGB=4H6?d2v&8y`XKunMrbUH}`|wG|r8U{qA(7nB8{3 z>doOj>R?6BJp4UF!kcq51+pRv8YKwMauiVDI0X0ztnUO5x;5zgnR z{}u9H9?MjNr4XA4z_{xu9UGB!Ru2et*u^d@;Qt9w#U_Giviyl^#rn;Tv|( zp_1d!&=5@cFr|Lx*R5l~xczpM@J{Xjvg^wMn(#jLSsO%!3{YTUNn3tx$wcESuZyLl z$tgv27O+(z@JS+Yn)109%sJ3K-SuG5m?N%7Ly{KzCL-dW+*L~=gu^aBqIl9W&sPY? zRy)d>NhL_?MSIbdVGy+GJM9bDmGcioE`aNs)oOg-$_1r8(4gYNt_Ys|`IdB2?3_ zbP+)qTS%MFJ4W(-d#h9a@>j?KM$dKY?w^7egr7orTRv%0_@EfV?FHj>4G_9az4*ao zZD}BiB2M1ITZ(LwUcPB8P%I!@Q#SaEjI4@>hvg6Kki2$Jc=eo9*TxwUj|;+&sJPk- z>F#XX>~*u|y#E{{femuzkt|stdib73Kmfvbs+pBtB>&0mYj)tgMSs5Di&V7 zb@8{TLYisMN)8Q(>q2zl(WFUWe^V0`Grzi@I?bZ84mrL&)$j68dt;<$WF%dpN%u!| z`@69L14+Vmgy;)2DA3?n$S7wZ$BoaAqUmpc`|AP_j@~_=e1?fPF4F(}F%K~25+#Sp z_xnrO@q|}Du=4_wEkkvGmF5dzVGG`JRE(xgeP_rgf)FRUsaNPMNn%lt@`cd;d~cCS zMWu=dIckrCB8-OE%J7qqIZa^Q@OL;Xcv;Srm?mPSL@$`i|Nr#01fISk5j(a4oNoDjKRIv)3z{qzIEYY2w=e~v z=>KLOTC71Ax&3NbJA;&$(TI@(G2%?usp2MEH8ee!hpifQpLv26AQ^&gQ^9mSwmjv` zK2&_~a}DG^osNY~y=?ZiEoqmaC#eZJZ^%+XEg2SFM{2$NNNpS0o%Cn))p*q*-CyPi z^G)Wt7!55;bU^Y$vA*vB3PjC<#C$5rnOF^pDrU|UX)w_jISp17$)_)P{+=@d$*hMI zC$L$^4e7X$Fk}HA_)+)Jg`ZJ?E^7>$-*;WD2tUtr>;s&OT@TI+pT+Q|D!$pK9KMQgnusk~fd z@E|>^1?Ng`>|k!&C|m;bBlGkYc%X3i_gAmSyhi+`Cgl$~p$eD0mfr`1Lbkr;J4+BZ zp`jC5RaJnV#1G-1sK!g^0`H#f>5-1Q;^QzS8#vFYn1i%`P|L0A;mGEQ*y1{2PyuT~ z$bH`{>C5ZgDHveNv1b|vIuL=%oK~$XcCrmSh!8Q(Mt~(*a;FMwkBVaJ8KKK&|L!s{ z8NbUhgl#)TUU~%s&s5EqcIbD&Vd(T^T_MhcPQ+kbJ3JVI=sa%eFu2@*g~=_-go;Zj zeUj`)V_yglH&!gAm6*=sG3PItd&DT_k@f12`8o)dHEI-l>!Zbo$1?^_aPX7LEeWvn z4i_3vj3UWRnNN+wD!%2!hHtyQD5I7gb)Tw#dUsV=Q!I=clbQ zmxU6?=j7}JoQfC6{g=lNy_@fTcB?&)$c}|o)N8x;-ww<1Z@NjI>u+Sqf<;>R`R(|-zB9y4bC z={ca|Qy150h1;uaA8AzSCyoojO;SBrEv7CclAnL>0A?hS1*7FRlwtYd;E=}Hz4}-s zN@!@v^h3+*MT#zQ)$%~il)%J72+)U$Lp&Nq*~<>vcROeMLkE}VN3{Md6|?7nF<{e< zeot&*nSnVYEh&*NKGtXyyA1$_e=t5TCuCV|PDYvpy`gKB@x-X{rlA6@dlry(jBDv*9Nz@;B23nl*#ixasavjpp- z_XR%{MR98xY%Z$04*Z;}(HpU?UnS^gcU+^<8$bW?x0%d4N^5)>hLep~`oD;<|CH|h zQY+({ALU9p4W84c4{ww_|!beWVSzrJ!IUN8lT{qt<DJe&}c3EknY-5HBy_siO`vwinu6=h{Uly@PAS8Sa~#B0d3Yjuj^( zFr^K4a8&jn^sD1jTeDj;hbQ+L+L~MwE6@tJq9xYHrB@D3Pf8A-4Xldc22up6-sqlU z3ZBjZxf>6uN( z@SL_(T`kh0?Nd?zvXG5Zyt?urY+4oB*oTC)8_(|I6yI0RjR*a#^^xpLvX`B-$!{wO ziI-2}UT`MqpU-e~i5WQ9Cb=nH8Ep~dhiSWB`P{y2F zI6VLKk~t8NnYPLWi04!2jzWB|PkZ>D+5BnL~?zza1ITa`tOK@AI2tnhfeE za)2fMVIcfgRfV;KZy|^rb+jw~FCKOqU3hxdno1#xW-A@m)MVZdAA}wTLIRr&oTcfP zswxV6=7mMO_Wh$iiOE-AJcoD- z-3-7!Y$1w9KA(3_PY08vdKQN?Z+V9Yqq1-2sogURTh}Wsa%~vVX}0SsM*&*47BY2z zFH{dt)n!t5p3)HbXeES{73a64nFC`VpBE~-sO31Pd|feb%8yW%d}Jq?i=u6j3_&;T zrPd%py`)Vj*p@l)pFNEWL4Z8ze{An4S-%{!S2kllk)0CG$`D2gYs}=PQ6+3Eu#1`V zH5+#soy8fWk|<<-90ikP#_OOEQum5}$E*-*qoiMR*X(|b$;}pIi#9_qFlwum=U9sd zY5h^Tl=*Ee+uCBFe9$_ow^W%E6`**O8y!2s@5gSo z1C4T9GeCduY9Md*0hRX8=CCR|gCRZqBh^n7SQoML43v*@qI$FViP?!z2t*~ZWrK54 zrst|VNg+IUwWFV0*dbEIM>zV#&N7ET?I=Y&Tfw^*zT$U8FisNXViW}F=7jb!!`Y76 z2%kUyXwCOHg0{dEH)_T>OZ~l!el6Eb&^67EU>f$l(_d6%Gf=OTA!0jFsTsQKeB|Xt z=wB8WsCzqqnSYm}F7sSA#g$C2gaz&An+{pvGxH)F1e>ZsWRop754@;sQx$!V9jU0k z5T$S;()3CeHEPfo-Adc;*$2wl+R4n8_zf}GuS8zLtsfYI9Y;0s>Bp#Cps$1wr(MjX z!)M2^;xxh6H}j1SuRcgJpN85>+Kq=-(N|iJ{e|vUN@iqAtQp5x)KI!TPJRAvz3cjs zx-Y1`^Mmad-Q#AhLU-c@F#u$#Er56~fTck`%l*QY;Foav15xxr{I|#RY2`6W)`d8C zUof6-IA=)+dEZg)kr3MFBFO%fikv=NLG@F@r!fVc2aQC~YAVyV+NFG?Tq!&fh=hyCsBGu6G?DT98H0r7w9V!dMzF+ASHTjKEHwLzb&?EU|1NxWjb^m z!V|u^Sw84Drw(8BSz-rcw{e5DASekWHctD))W4g3gZ(6e#E9Jpz=x&nl%eRpj0VPH)p$@c( zw^&VjLDq~uiX}#$VHXvR%;EPxAnocC#8HA%xj5~NbJbk3JQc^eOt#l5NsuSJCE)EY z5HHGQR^2yjl`5loBTHp=G5zena!WR~u~5azA`?lIL3d}++%d~3e#8?oXDtU~G%rDH z5TE;hC^EKEyE~$vUeAok3^rrYOxIewp+{E#VId$RZ(zS3-&3=mV z0|c`1au)F8Udn7iPJ}yt=V+t#HLYd}(fxV=dHAsL4c@40P>S-Z^Ze_*s2|09#pK|7 zaz@X0WXi%;nR)Ji4vFaE0f1+fz*OIZjUlGNb8zdED8B=+#)U-QE)$HwL~5VeIQw;U zCQ#X={zfTKIrv|0-P1wG#5A61@5;_@l|P(e^;-Mdek?U&Sw{ahwN^0CP#J<7Q6bB46}H^6S%% z!p~m~<4-3aqr<$dSKzwUii^7CCl$MLY#s~43Qz0Jh1ViA5h zG-?fXI7rmKjeN_m5nH4_aLP=;FmCF>booP({gcy;Cp5Q4Y}vHZ2Td2;HNNHPkgid zp)+V2q+=hRIpah)1k}wysPd9+A#8jQdKbG@gl96+6Ml$w_4$7%)_^4D(aS>o^O*V2B45w&H3uoNH!GSD_I!)zkkK<0*DNDo94{$ilW1v>859ZRN zy{b3Dr^MNpPLY4Mu>_S@gG%B>5G2g3vWcj0R(i~F?#|XC5Xn}gMLzmT6vP-{66kx) zDgmyv_p280O96h(8_Nzu6OLGo-KP$F zY-~Bnj5*03pSM0>qlQA+^VpeV_>wT-F~EQ%wQ%9;b%hsM;DlRw@Rv&PS7*-u=lSS% z?BS3IU?8kku+uvoIHS!VmCF%DMQDvT_O^3!nln1*9DHEH!87+{XckGlt)ZsM)?D(u zG6>%%d|84SD_~_zIs{+>1jR|iu8j!tTI@~XT+z8iwc+#JmKBm(u=yVpOK`YuU)fh1 ztAj2%X$HL)@VMAqizl4wEitK+r_LYNv&qIEvh1}ere!O&t-cR?BP9I^OyID$%#_0a z+{=H_gqV~@#y>W|H3lNj34WlXNM&Nz&NbcZ-x-mBJiv~+;>Wtqgby<8WH_-Ae*|ZM z5v3us)7~c=B}33?QwZ-+6rLpUurj(QU#uI1v_`qY^L)AN3^cYL;{0mzM8D>Hd<^&1 z#^XYzMDmB0rK&~%3!mO##%P}HLA7YLV0h=ZA0@`Ch(GCdnf2a?sD~6>fUIY+WZ;_X zx-VYlZNayUP=SL+fyaigHi51$hd^`L$!e$VQ^Pb=$M-ezk71Iskc!gKWEY!FyUFRU z8tMR@7~X{mdi3#{0HygWkzKUYFLrv_87>%GnD)ZAgvvSS(6zIAp5*9^OcKI&ZWY|I z+Xemae&7DizvJcbItv%ax_Hea@NDbk+)12bGpyWlay2hDm49Yx)}*rq(`lY&v@rEq!0sfR$Vp`qu#> z^!3=8*mUFU=pp5% z#%hAk4Y^I0Wa31EY{yEM*jRmjz6Z-1+zmDlMIdvS4VnDLvaTNm`4C31fGMC)k)w4X zYA!K~>|n1iMu?waV{Jl&6|fUn73{uzF}XI0YV`~9#~2%OVx8LQMl_&k53BRg3c8R| z4RK4)&weSj5P{}L5|=nE%H0sbg*nuYe9z;|lTUu13+8vbUw;Oih*m^n)Vex4;F<>v zeSdm^IcM<>|NXyzoz~r#jr|=k0`7v|NjG2j&x@qQdqpkTbH#PoOfgE$W2($%!5GfG zL}#k_MlkE$XU{p_|D9o>+m%!Ol>9J5bk#s_o=@x0*0^tc8jd@7(d@wO<3rAzBz+xQ zGAhr`YE&chSs}B0D5L+zoWyma@d2~mk7dd6_opdBz3meqCLLq&AaU|?>6f@mgMEbRrm2q?xKwb)=O>20eMO3lRWGgKsr=98 z2#N#^VMA%mvpvXYNDsEk1EM1GzQyugv6+eSQx_%u`ca#(+pElEWFU8y?X)D4I6H#g zQHM9Tdhskuecv`h&+|IpPA)((etdjfafbWUx_oTR4w6bXJd(`!X{jJEI-1RgbcM%- z?*)?#BX}Jo4hbhLc6h3UjieLB+J?ydvT`%+`CXR`_fv%^Bk#&)Es!qi!Jfq&SmX zyg*wckp$y@R_H{k8aJljf-MHrGiC5LoY3)J%H;qo=FVH5Aa&^3zNj-f^}@onR5Xk< z85SME{=x6*U&Hrn?Rs5ljy^@GIlm>i z`N}GCd#GY+ZVnGrWaN)^PDyfC@T%rNP=e`37n17ct+?Ea;70K&Dmd`+W6p1`gM%qx z%*H!2&!AqVadxOooAQeoo0%0%!ff!)UB}?ZbM#6-Nd$hEN-D8Fs;ot~;90^7EpG`o zotj4EF>wE4;X?KQUVzh9ulw^iRv$kogKbw|uCHb!YT`rr^Q?CLtJ zw^PEKE<$nbT`xh@r@pjX6-BIZ&fuxmW_F*|8SB%p_0shG&&)=# z(u<$a=-j2yqhm`7KFHNqGq@)c2nV7%*>2Zdp7;$QqXd~KVnHWBJ`rHB0?08L}AIAA9#+7&kn*D|NE8)|fe zGXnz_6NI-ICB!p2$Phm9F(PnyJh61%iN|q1VyK`RcU3F}%A;k0Y;4^Cux4~V7rrk( zN!to8$++DDP5D+A{HJ35X{TwN)pJOar%7$4*^)0_&|lF1y4LZBG(m453?XRd`2OF= zc0^w{-;oXbZpT44zL_}%_gbw>+Tk#Y$5n(rp?yLx4mHBe0RjWJ#vca;6Y(A=HZcij zrvPdxBJhtTMtE(2`)_AR9HV%KM5hJ+j>sN!cHXMk={ZpKK=lZqx>Q_bVW>%V{Nm#Wt;HpI8$o(ym2xBaj^rk594N4Vd%D%7QWWBYJEgD5y zc6rii4>Yohjk@2&SRFiVfn}RuGR5HrGfL3_R#3mqFK9>NUo^t$C)R z(`~|Ne*5k(fGaD141(b71a@vUekhd#73|FK>0+F*L?Xkt%)&4F=z5IFWp3=RC5h{- zrIgG3I^Ugi^yk{RDd#iZ?YafU%Npqdjkpev6D$u8vZB#4ygJ<;we8ns8Bd#iPiYk= zk58$m4?uqH4@R!!e?+TRu_LB6n+?#*U$0TU&fp0sfbb*4^yb-*nN)A+UuEdG-TrsX zRBsGcxT7v>V^Sz(219$YGg$l7vLeKaFuQF_MQDF_Wd1NzTwOBEdt7KFR5l9uRU)wD zVih-|guV42hD1uX(XnK2bnvyD?qEdrh@!nXUaM;$2Vj*u?eSRZe$_1jqQdHKP`#IN zj^BYB(FeMMZ&%w^^2IdD!fo@z--z&Sl{D0QxuEFnosD!%y=$DTY8pMw8Un&@&V%HO zLZ?Vj*M!7zg%%jL?eGHqgog1`5{+wWqU-$73<|vWgXXkML z(z;$ld>yU>WBf(3lp3`rjdWE@tc+_k zQscnV2#+0D!f;ZfQ3hZ+Se9W@TO1rWxPR{uLrK9TTnMnNh>v59N2)wb>s%)``6b|0#-XG!Ad4JD3R>|xzJ!M$Bwd)n28f;V;O3$XbUDTY&-UOMXQq68^PFD1fu z5BI?S4;+(-;LYb>r^3#}FY=Xd@Ix8C|i96ERii;HUk2S_F3{7o4H zHv?h{-3w_>HJBy8Y60@BX4Zf)%6iWIrlO5OmCX4=1sg0WjnUqQasZ_@5rJl)2;I4z z^+|aufusU)#Tnz1ga zHRNasa(ED0`S@dNpyY()ZmNj{xYdF_x?h{ut-*6nJ08bu*?=t@*JAU!MQq%#23t0+ z$J#Y>D7;jtEb=GRfdvU<;8%3h+h%A{F4^9-Rm-)qlfDv6bos0p7LCt z$l3_}peMRE_>8r&+HF!oZ79%-qByMhAmm8`~Ud;xb0it0`Jk- z#e%X)xZ@Cl!GPx30&Rr3wFXUNAVh{N&wbbrH7~jME6D zpOWOhOE13I6?qQhETq<0T3W)!4eN2k4L9JtbI+yD(^||A=J4=C58>l~{c+s(t=mxM zIl1a_=3UO{V$EDj3_(H`5qXy6Hn;51(8d_(SY7_}@T{4eg41<0T8`sWb z+s3sxaoZ+5`_$uc>G@~i{_Z$6`wTlnUYOf>xf}(K@vtusFl z0_!(zM582rboV{b)}Y_(!8sb;9(VllH|^T>)HC*Z%60sgU3S?A$}9sD0$dvmmzQCT z!9_24Ax=Bp_}||BZtU2x11l>lu^UOHJw!TOJtQP( zm4l=&{Tf#qyAIU&@tz6xE;rNJ_I^_)``k7lrjg$N-3Q0i#>G@R=g1ijAx+OH$Yu;V zS%#jBAnOrSJ%UxW|NI~7X6L28ziEDc`?aj+>t%Xos~@^Fl%kz~`$GC&k)41?BGDA8Qe z!5B;5^MNG}49Y~s6ctsj?WFsKzbhC>sLmC9h>P~n6v8YgcVVBLHkjiNpT^oq8UIqsSdNB6g zgAYH1wTp}KP{^17b5vo5IZ#zqN6duoYDAl+fo?92hCw|5$|w_f?RFP!i(_dd}Zpuz5VBSl0AeSue3a2PNc%b+wvGigvu3K5z#8d6cDsWc3g z(x|0Gt&LB=bAD_?T!=uP3v726!c#mkQhWPl=c9l#&b$JG3Pb4}$s%imN*T%^@bgn} z?l~-;Z^3*RinU&5^Xhk`<^mDI1E6qnB~amjXpbihxWo^aKaBq4d~?#tKV2H6A(8;M@}yuywJ- zU_esaBbiL4E`2}kwUM&_LuZ}-UMR8y6d#I%)qDs7N|4GJp9m2!j6TY;JWRgWEmT6b z!PQq^4dV=c@5bN5!w)|Mo>v(hcYj5`Q=x*uRg_yeov`` z|K%^a%!y1uX@#nuVCm2j78Vw8<;$V* zeAz2wjO}DHraW_JV3dh&WT^p9Sr%;vZVZ$(F~N#=bH4@m7m&kbJcL5@eAb>=ew zh?teC2_ocV4J|6(x@2X+Hz3PktVLB-V{Y>wvS*c{bkm_P67N z6HbWT`m7Bk$nZkdpOTeQ_>uX*mjf#e9yw6qktKD77DI|LB1Fc?3S=aK|IDw8(Vmi4o~jGcU;nGGe*djG!*yC{m+a)kWD;T z3DPI6JwxdL1>v0zEu{9rK-Pkb9A$3~y*#)`2FRV@dFy@A;bD90ESPm*mcw~BK-*fT zgEPcp##jsEh_F`(1`7sd9Wn<9-V)=a;c!~Q$O^;CKx8?xyoVwe7}Xs8oREOIo&XA< z^u4ELEtllJeHBKP#*S@$oVa-oo7WV`68JwIeTB6#Yc~Irtc{e}AN2Yuzhl;QI3AB- ztwm837Xf|e#S^93ibfN*Gs=1m(aU>#g! z=W{URqBTMyGoE~kENy)%V2JDu1zQ#nA5HS-Kn6^?9yu7Cj|N`1xCXs`AK&@Mf5cb6 z`VYAN`gNF_o1^v6D{$JGXX3ffe?C6-$xlLAi=N0MkKn~GzU;)WfBkFsKXdTU_-d2{ z%LJ;b!gxG_F$(9La}Lft^GuXwiKZc=9<3C<`HgSljyvu^S(ao*V;y8w1I|J#J0+)c zzJm(z5A)#+);qX`MZ*}2QKm$sV`%xGt#xE0DX%)1Q!v)v59hS#yOm?8c!NU~&p7gs zwAZ~@ClyAfm7UnBZo&dqldj!pUvxM;?|IL|P49g#F1+x= zN5^>hU`+>|KS+#mXiTfIZxVLC@pieC^G+#m)?48cE5C-46@}AGM*iOwh1~c*m@!)E z6&dwv;^P8Iiuj4$FsmXgdWm zqjZi_2cCA}lA8CZnJ;r9^TDGEIcH#k!8i`47>vkhZTmIRXfGLc4&V%BCIASZ#%F!k zelL|FUa{{X>Pbk6plV8~eyaYv6yjiU(GuB@op2w8Nudvwc>X*|NpR8yz!0y3jl`qyyy3@bZ7~T3357hjxr#e zkKJVsP>Q%9f`gmZb2h2KM`80RO?_-?#nBbOxO)0I@XhT?H z7LL$`x{iA>XWY9A=FvkSAg#_gSZA=ZvI5mKcx3l(eEG}&4QHHj1}?hjB1o+;kqR3& zZ^SiMUxj<_y$3(K`$y>IB^)b|WdZ{HzNZq=?rjQ)?W(?HIiD zr7y+NM<0#xcud`NQQ!yP`)7RR)?2aX(LGqdxCjUV?d5yUxhbnin`}Nv;Ztwo6HI%w zHULLtp@sz^?6lRTwZ!%}AOt~V0%cy%3`^T7M*d7_-4pbjVL+C|a0Y^*vCu&lm5}vq zAfq@7<3e(vf^iOKpLrH;dhZ|M#V@&RX4Rk0_PUXsvo?ad(b%&>kp3eFD~uWo;|+9D zIDaAyDoHSY6K46|PB(;g|M+lB%n$f0*W)FvG2p}S5G_3$$!q`GjsS)@q=g7Z^EB?RXPf6zPcj~`~~K8=** zaK0ELauWSs##v$=P5)=s0l5H&fDlB8t+a)b4V-EKE>M&MGAQB<%s4a-u&(6@(D;GW z6&9@o(ONIT3=%>wZq@*d^F9DUwGyr`e|rc)e{2!sq?va=lv+VchDlSPS93c2bAdrg zu*nCR{suYdjPv3KuYeBe+16jDj>y!E>0i~}5$0LnO| zRCJhnnH-@%?PG-lIend3o}AU4U8j6b&v~oxle+T{W&~>V4XuQS|V=f?gQ_L zC!d>3Y_Xl^bXh+JE{YOaCg}ACD{a5`GR7hD0_)bU#rMAVPx!(YzJMJ&c3|t)tuS?s zGRv^zgcI@dD_)8R?%jz|HO2rAT5*&`iRV7|dG0&kd1~1CK4lL6vR6PGLm?hzi8YMj z(idHV^UpgEgTVl!$pmZW=5b)(e*FEdx8fha{cWhG!N|j9+@nvy<}rjpFl*x6C-^`c zXJ8vMbrC6Jz;s)g8owYo7cn-M*wPt*ESl>$Up=PttMsDne!uP9Y5vvt$4e8eC<7Yp zBKC3=1p~mscr}1_4#ypPEZ+W(x8tH0zA#>--7cX^RO)UPVM8z$7*-m0KD2@d_BWU` z#{1{Hn8YT7wXUWFyfDkx{_rP_KAGjfnyD_|_*6RWyZY4*e8Cucy&MbuJ{A`Sc)_`+ z;@T@N#P*{$VQ$c09WiPeG)*&Q&eGLBhm9}K^B6&^tV2~<>>o?)Uuk@IZ=iG<^pge# zO@|1D%_W8L!yn^$C*96JbRgm9Hi7~=C$p)|ejVHDwc&%X%I1D?#8 zIZE5BY)iyrj6)dKdhX{XAo57M8`nCT{S<;fw>M@uXTt@6+BDg-J6+RZE?Gl#&8=8l62K|7vx5RyL2jAw`Co(PelOw>|RD`=&tph)C_ zV3;YfWPuRs$%5fpl1($^`ya4Ufp(ng;2;3f{d0jvHPBMQSdvjIPq6F;4{;w?S%{o` zW$FsI-F6$E``qW^`s=Spk!6sL!eB7KInRDJE_nV0xb3#v0XY1BgxWJ z>hh27s{R$bt6WZ3rQA_DEm9OMk|HHe-~bW?2@W7;;7xZr!=C!b+I!!9@4F8mCCjqp z=TeykJlye|wf6efH`KD4v7kecVc>K3VBt6 zyF&Zg>#yVa=buBn-9de%F~nuh22H8glZF$sk7wmJ5b(}@ zo*~Kx2zmkfzXH1BpD&zDEqP)G*e*)!B4248vaKh^$MG+}_BH&oPk$Ox%0P~Zi&Gqv zJ8VLMYgm_BCEmGI;LLo9g|>8LGio-KgRy<1SCOk;rTUw`QWB=hgN?4$D&)tjqD!!T zK}`L);ghu|!_~9XxOwXa?6`gdwr*aJjaRS1>X`{ljE`RNI?A#vFs(g9dU>Iyh}mYY zvCys1F344IsnA&LDCCvuHFLZC^YRwL%I)T@o5X#S@3$a!z6H9!i5v7_eB+V??Eq@v z4;9`DS6e`8B1j76nz#$N(eB@HcWClXdj6omB80(O3#m1_8Y7uvr_y-!Oo3KuuxH~4rbm-y*T$fK#V`mxZbE~y z*LX7jAh5jG=wEK#7B}i)aK3*{EA9P<-S_?=;CK68A#kO-k)|pB@SER6tJR`Cwo(8z ztfut}*MJrrMj5aq4Rv@BuJ?*7kNQ}5NDZ}jNLU(oWK)k8#7J&fhen}3jKOig5H$Nq zjC67V#(~r%&`ddpNq7Bvv!S@BSW4Gq+Cn4=rl+TH@!~~1{`lkAy?ZydY}tacEYaW% zTz~!bxbMDuapcHLD2g0Ol7YMHWbZAv+817Yj{Spg{5S31J+GBQX)PEts7eY;*ni*v zwr#%wN-J1pP_Nf<;rw|#{rx9#>eMOJ8+Bx9M*8�`eD+0brdJ!(RX~qcirxw|03N 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
BDQdUST0`^#|(MZK3K{<5W70oXwd} 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±}m@;p!Dq$3E zw5+U>jL@%-k+{M5oIoRk(hr_W19nG0i6w;2r@Y=vzTm(f0YYom0;H6sz$t-hBw|qs zg#eV8P6GRf$~)hV?6m_LSmuHX^aHPvgRgl#;A=j_)|_E z++p+jo6Mj4AU=%@Ye&WujCPLx>q?o`!6_ed~=k z_{x{Qz~-%2IM9JbYuUv7JRNtDF{T}}7H^0`eN%RLxkfG&}Iz*H&gPl^^x+G58FG;sXrzx2vqS+&N* z+l=WZF{E58Y5v6O(r1Qrxw^~TKFwCgI`=nek%JUv%rA5-L+PqisNQE|i6_GqY|ILx z=nP7{gu5F&zx*4@>)%LB*O9ek(TofMZw5vKZ?(_!#i#ylUYUN9)AJUjCrKiiBbH*Y zqRdTXNQn@38HN!FneV?6jskzt1~A`7ZzP_x};U{hPnVV~0=Bdr$H?zpoYt z5*f)WIT1rLQdk;+Bo;$M#TIde^OY2dBStT{fA^d({o!Z%>hJ$k4$j}<`GsRU1X9Q% z8YQEq)CQKC*Q_B3ld7hf?Gto^OoVjdu_4ls=TFW(LS;gBr4^{lY0WVq_{*HFlnhY~ zY9cyhUVs{Zr6AOV(ZJJ>Dc{w=MKBzP$lcdp;h<9XjHPx1CmUhkD5(<8LY{38B)rM_ zcus_kcDsT+FqAfu#jV_(g2~$>o(0`Kzu2OWY-QA`MDO!W7I3; zy!E@_MI{=|?P`^iRzwoheIX8p`#(->3rl`gN6zO@@`tznbG~r&pYhY`BY4$(YKFuR zgj*M1l4ehG@@M`#wzocwA+Yifn8`>Vm0>;bulg-~Shn!#e_zkoe+=ma%3NviUYDA8Z}$YY6Qtpr?vjUbw^ zjSzkAp(HaMb4gTYN~UC^`4T~AH240o%YUC5&`kmth~A)EPiTZ_a^LsjuNmHXDKWn5 z@y(Q1ZvHkuc=A8xZuKN%Hfv|MkXS{-Cgc>{gNbEh3^oN$Q=*HR z4Ilf+rt++;@M3Mbe)2YNeB+P!`}ZF3kw5dN`PEN+k`*h$IOcW$&Dk87V)pQOpI@{z z3>gWPM&3I)=bNv;%(p-HHO^l9KCAV8{;cb{zI0r8xVQ0K_{bna5MfHHgoyzg3n&ypV{SDDFSIdoV3omd z>F&JBcmC)L%qqu+o_~S5s_?@|>=mOK+%d+UesBmCH6s$0(R+M=aqAgmL&~FkR!TLNjoG19`rwzBChd6``uDOVWK4f>SDPc<<(j?1&^W;BbujiLL4H+_; zf)ahi)KWr3iVWTWUDmG%U^K5}r52YkQU5+dg8!ulKy1`Vh;_8g z5UJ>E*mn61_QkDJ$z{q$l#o}*Cg1qMm3`*An0xB{p-5GB`-N3!yK*?piab4(EUcJY zg9w;mBsoj4FgqCe_;0~K{LJ%w_4e=Z=C$9a5cKH~g6ZeRR>WHN4S z&*dJ}qdcBq>m$YrcSplX3`{+o#Kc)G99qND!bgX3eVS>EHMbZXVob zQ-kq>4T)s83^8wRQ;2MOk7|dFp10q<%Xhy1b-w=6=V{)4lTYZt-c(s=#p`3>?e)Mq zcv@9j1k*V7jiMn^*Ot~<>eWqd{<&YrF6P|-<3C1y;B*tXbJnx=*=l<5LBnjd1AwO7 zhz>=)xob*okz$90$bd<^sBpasQHZ56CX{Kdp`9uFGhut0eF=Ta=r!LZgv7)NXF*tm zhz-hx$?%{03k8CmpYT=LbCX%;S9E@uyfF+-9s3 zq>f44aNg&MxJ1KAKX7r}Vfr&p*2k=eo{QrPUjNbSoc#FPEKc8KF9r6TLld0%K=1u! ztU*~;QLCjAgW23+d;c!+)^(y*{PfnZarc=I^TJpEGSkz~;w$BLfa4gs_Cdpof5Bi) zVDKr2;)GIV1x1OZa}cB1Ft;gN*ljMzQk7W@S)dfLJ}U$R9yX3xWk+o?ffy8R9Aa_{ z5Qv}_6BM)}^b(S!Gq;sRGN21D*4MQF(e4)t&{ zdIre@m_`iOD&bGLGwz&S@Wxlp`1>dK`0&#o!_B4)|1WFr8guJ*-Sz#(m~%eQv(|bq z`+oL0$HzW)VkbCp9O9(p)^HKml&T+4+o)9~K;jE6Y1LK*A&P(oN)^&prNseC3!;J+ zDuf`VQrd`;q7+ELA+~Yi*g3~Ow|&mOy|=a2bD49Fei(DTud5o<`jI<|A+ z3)8~8^TJX+4tp>|R5?C9;%*4k%PsF)bv%6OMLzJWzmN6HFL3s`e@uPyh zvZTxhK5<0oT6~wb3C$rZzzUY#OA$&#Uj%XYOB)Rq+yy7)Kml$8b}@!fNnP~JWUW+Y zMysU7jUz>jU9Fs?Kqv4*N~|_(F19;Xmf1< zo$!y2?{f0utFShtD7VxYpPy4pW+JkicZ}1HG|nu`l><0)q1!#<#qAkK8XzS0*-1rb z#UY)Y8mfVn2&*Ji39Kye>ih=#tDon+`~Wqjt}|nIpU;2%_w$YWr#yJ_Gfb8^K2^T& zUkPkB)j$8KdN-Z|D>up2>7b8kQPFz6hq@+UuGn*-bgct9!@N^$4R)&{8l2Oz_r3uu zx76yAsoRL%f)b3-3s!0gDeMYilA~IFIbMK&<_2KHf(4UoPzSP6O?uzeOb%V<7TLWk z)MBVO!6tGO9aow>81a&*EUgz1TC)THeRb~#PoQCTQwop)MpZ%g#%}8fR zY2R~%;l$XS!0wq6)qj4JOr&GDb4*wEuvf;#N7U;goZdM_ZVyavKIL9#ygeHOu++k? zK(C3DBlaR@aB2wMiDMk|51aF>B z6~@`vS*BDYsGEF_qHxkjjyq+Ava-l-&a5wf5%TvTDPuVjw#N4M2l(7~{t&BA{bBB2 z{sX?}H%C7BF~z2Kx-Ese7-cH10^Bvx<a;PVRi#>Wtw#0Hb_hnu zo|;v&z#6Jnm8tPDWTrPgsFlyOt-YqkM=>OZ(Ilq$9^8UjMJObLETo>OB2 z%1z+CL{!|8ONG#sPo}LK+B7I(=X*v@{^PkZC-fji@4)gQr>i2#F;k|-TbCc=FFg9s z_{rzLiLwM3vR4<2P{h5sRRTFKgc2CH6)k&)tJhg4;iU75CHBfbXCguhFp3>KOKg%m z*K&o~BYoKx;q}S5>??N%MPuPZ^(nPHXC5o_0#9aR|42CxiO+{M8UnIhvdSZOweVn* zSW{W%g{KRg<;p%UtOFc(fpv1y(ONo^!VrW9ed2xJ{B_iE%l@r*c>Jl)xEe247Aurs zkPAIV%9Rg&sOQf8*cN_h7s-O<;=v(JnBpqSM)_^&HP`SKe99vhsAedBBB7aKReAX% z!t*cHYmd=1RgRBW-2KMy2y@AnF|34efqcz2fM5AvKeoUBNABi0ve%Ja9qJ`TGD~h$+3XKZ^YGV-^UEUC z;)WklrvgjxF?3lPc!Z_{NDWTYOhKgfGo2x$U_q!_(F(tC@hkZ=Z~o`}!sG8E9u;D5 z-`soX%3uPT( zK#;kx>IUBb^4BpvJ?C=Del=0pZ5N~#LZaE5;r1rd#mrk{VbDUT#;BE1BAXa6Q8rb$ ze~2zr4->UU*si$$8JwWZ`uGOLTTlmfP4|nNx5VUoFh57y0q{hj{hTir?_!Uq>{<-f`(-1v;TF zE=F>XebWG3di;0p+jD*hX-bX3(ly3H6l?7ckMA`zsFAjrrer|&1I_X zO*Klj?3_lF50TBdgDMQ(0HNi(|HF5G9e?`sKg7G+ZzhHUyGl*oG>nsDujL3&F}V;z zN@PaV0%8A{TDMF!<6>U#~L z8((GJpYZrIpJiM!<;#zVHIR=6hG=BQh^J#YD*H&u=pqn5gvRX@`>NL<}*JwG8GR2eZIZqolpNi zJp8tAV=gDHvKSLZaeytE;Q~{Fyg?FLhP<&BOnS0kTgS^Z^i0HJCKvqamFY$`>wWrARH^CcJc zCQ=(c)V}4eha2jQs5hyuUBpXs)Xg`k)nYe-i5R?6Ai`XGe&X40=Py3~4>_w38Ty6g z)B_Z3QOsPKR~MHeN)hH0L7um!LJ;oeC%liDkX@w}hv0z4y|JyAy!j7*nqq<5!)@-q zaF71(nv1ud@XnXN#8O>&GnqO(vNN<4UTh5fi)u`zP%>PK(o130POV&FgR)9StilRm z6#`GyywoSK>Vz5tLlRCjaR2T-hT(+q*%L~DW%6l)rb2#v?$yW&ma?#27QVb4xtfg+ zz9{^f9~fAl9-_jV#aCTS-gBSURkAIBS@iFteU*O5>U*>#&&bTwA24;iP{d3agdtBXmA9R^M2s%O- zI%;v2#npJ9KmYmvl%solzI*dmo2A!h+;*T^wcD}n8e0Xh5p3_+JWa0m7ur;8fw+f! z>a0y|U}swdvQXEGMt9v^)zm%^_@ypu)N@vxAWJQ)h+16Y~A^E~zi^r#AYe30Xn;l}PsL;1Jp4uonwH$!xcYoSg zFb2p&>kTwC(%JSNf932y=Kp->x3jg5WR<*evI|iuV@oEgm3S)TCqf<<(y?K;gmNKB zG(L3iOT7H`nWyh`l+nmcEDKVl$odp)pX&4c%Sly$nr`SbU%abz)=mW6S%i5+?cP=jJtsIj7pgGe;NM}AG<_6Gx>{aYjNd^)pVGEd%mL{)g< zrT6pjJ6`7a^PlG3FTBatlzpjOwS1Aqzj`)i%$;zo5n|zr>R^njj8u+svd|L!y3tGE zULOe|(x-s*nf>gL(c1*>e)MDLSb6fFWx6VdykW}kl*g>AF zM{Yu%0y>y$0OSzv+R}&&YNv2&$dyrVDRp-clevbYY=T?nt07~>j-Vu^m`}uX1eQ71 zT#AfRQK`1nLdSEU5}o!>qXR&=_vBQfrE4{v=>=+a%5ozFgVc9l=4 ztzqYlDV?1LWc%78jl2gyvz^OfqiBgSrcGYy31Pgm{Q!UN%Rj>3IsdmP79CBe{*b2Z zfC^QiTW~_}8I-)BD?@fhm6NxQ|Cx3&FfBomUbrJ|mK$gljSKiD1nzz}TMM!44 zx@7m(TkM{^#j<3&uH*j8uV7`*xLe4kT#6ATP*ph7nI8A|=lsl%Z2Bi-Te3~KmmDqVlds<3MuQjf!v76zYeddkb%;j8I--2)d zwLRbeyH>pLk>s6aYss_bt~*pclfG6eq3sEUnzbc?H{l8Xdt7u-67yziS5DZ}o|Zd|d89n+&nELYFbWujk2P9NOm{_$=4>Z8PAt=!f?l!#g7 zD8SHrlW>)URTNHB;6W4~_O6aQiHZ9uAqiG7(Z`-RbR2boBaI|g`pZkYr)OB7T|3bw z(tadTP!{UAW1MD+g_eWj*Vx6(<*v6T!s&)D9(@-Y6I3ONp{9gBkZM3zo@#y0Z9YGL zD__6*H23>A-CQZ{oQ)8AH&)eXp0c*wv|X%axYiT%Uf8ak_Ol|{Uz4Y^2@(RTk+KQ| zv;}KKLZ1j>#qxZ6IX`*)oGMmhE!oIA=tR&fW;w6I^F`SHz_$$LFa7NJ%NzsF$(AdM zEV;za_H_ zuD%p`{pUKKy-~T?7b+fM6)8Lqg?@X+aqr#c8R6O06Kc)e?Sx5{Q|&2}vC4)X9C{4^ zs#58q-<_igCwA|b5dZ)n07*naR7IGju-}N>k4rcY7vsavcR|)OQ{Ie z=g2wm_EOpJCz2}1F9kmFFZF!%*Y>>da&W-J?2bT9jR0Pq{i%zOzN$I8y)?QKG;RQP zK#9MdxWAw#Mds>Fx(HSZ#l+K_s~djI6jQ@Ofa)V!3$FV7#@{w@>+2&w|6>#TN7Wlz z+be1trG~r^R*Ch|iZO`u88Qq<51Fr?vcEiMj0LsIlwnOE7p05-no1RpiX*gZ7a2qt z+TD4Tg{inFB-I5$S$Ausc!&z6TxaxIs)V7iUR72PD%~rUt}_f{+E%ttMvlhM@RQ+; zojxQ5Wywmat&$aG*;I5@>1*Nb@gsclOFzO7e&~1e;nhEO5c9_G@OAQ}Y@48tE?}yo zk(2uf4h?coesx-kH8PX*K3bQ(qS;td0gZ^Z;2c$gcE}29DWlae>A)Bk*%x$I30wAZ zMdDH_W7tXk&420t4-5TgZUA~Bfoxq})uAR5dD^jBHEWvhSWHb!(y}Cjy5PdHI@>-N zB)1M|a3^3*J|?u55lH7F=}+%I!GHJUM|exV4H=4uq^g(8rogQxDSj^Q{<2JWPbmWB z%;3_H5U@~L`hk1pP2N}DK)XOVF-~77-1|`Fm2Zb%@r!{k{$qISm*DJNI9p(C4sx63 z;t-u#*w4=>3Y$(i34w=S_XSAzI+zS{3*D#D!VH*Qo5u!Q5+#PX- znbOtZ3=S&gMCoupe?LT`3Uerw2rtLL>7B%@uL|$~c+Z0uz=HGl;#{vsrr{dqsff6f zu;5O)&^ukWNb&HWsx8?kVv7ffWHUm;r-fpeGh$IGm_@{Vu>=alg<1nbz+&a4@94Pu zzQDVmUU>ReVf!UPo;gb(&zTx7QAwjS1_#roV zuS;eKL0ASwYxRH|g}m{?xt_Z8d_63&WI_Qwv{ix{yN^N7mD^~!1X8d0M?BoBMH|K94hI~CYO9dLXOxa%) z=EXx#auIG>Wr;9!$~pwXG;&uf!*NG3&nuTn$kCIHf>yRw(Q0(X$mV6>K=D%db|9^V zegmiXgm`4EUQkvKgl-+tP>3NSU2vLmYy_A-pmlc7yZ9xtHp=%QS+%O0lN|J5?ysog zr*&hrhG-P^MP3^+pk~K;R}&Ak5Jym(d6G(rE_g8!q-Lxx-q*>7S@!l%%=Gt^5B$2G z4^$Y>jon+u*=vFGH;if9l8F#PFl-Psyi2!qbZcdM<*rK6fK)>}U-X;Xuzn$MdfsaCim*SQSwdrMSsy;EDL3Ww>Sg6y;{qxW9 z#pCZpk37^+7RY!8xL6=O6Xc%j@=JoBzxodT)a9S#cOU&Aug;(K&i?GZqPh{(T->8a zU}u63PI(g5?|8Hl!0)}=DL<=Q{Uv6(~!WRsC1 zXe!9N=JHX4m*oo(MndsK+8F%9wyWxF^>yU-#<=~y%=^EqGChxM-x4m~Q!Xw7`zvLB z=92)e!i+LLze25W(gjKv$Xe)*jnccXJ6dKV!lpC&0XD~wUZ~uDC~WQtX(OagT+osf zS(O{5-qOT4$x-Q2ibI%!Ix#jS$X}ttY=j-EBe~67>{Az)YgcV*N_DqlQSX}5eg;{5 zbLiB22ut^o^c&nShCOCt+ml}_6o5!4!^hrx-6Aa zYpZa~USW#8vB9eQdhDun& z7q7m9KU@AAewY6HyqZ3Psp|rCG(-(+4RKvLKO<|Q-U6L`T3{=`7P|WtH)nONlBhzN zoM5f1N{BP11IMxncfm(x$&Ft8_;8;u6n9adTFD&!s3-Cv2%Zk6qiWq0zY&4{e1HI z5A$Ssg?N;`Jv_m(X)KBX!evFp@6MgURzXgT)DVU4WUDL)`Ltr$H-J0!byN!4N6%wx zjdAS{@XP9|!ye*Er9YZEeP85-SbVftg}R4%D~vm3UNQ+M>7?FKXd*_}9kQ}#V$$o} zc?~!$1ScJnqAwO{@<=P!(9~;**r7#S+*Vv_Q(MYGq;pV{G$mhAq$^;-@Bb7edp21$ zZ6Y3*#`>o1GGHx=MRogXFrQmm({+fu|A+@L=yg}9A-4}fuw2`R&HR+b{AVn=)!Mpt z-&G^5eB&{3@Q6hB9faGkzT1?1rFhfP4*GES)mrguPSN&SJ8LRCS3_E7WD2r3>XIQS z78Y!7&CK8nYiVDFERY9-u~L_StTS<2D5u8l@oltjvE|t9$-NM|fyESAn}5z%g(MM6 z-Y@ERh1Ztv;7^55@;k!s;~UFQc|_ji(}B{+Sam7L9{*lX+c-%4gR~UM31kaP7qC;g zrUW8_~ zmx#SnX~Ra*SP7+}!-`K3q;nTl*a-ubdI94KbSad@$VsVNA63m(Nw(#c@*1nmwF9iq zUQrNR;K{uGJG{q-AF`%5j|W1#T6KzVVp0Jif(`JFCq; zO=&Y?N2gso@ao}3R^Rn#X{e^np4)^y=FA08kf}{i9?;?oqc-oTXiE|?_02$>Rp&*Z zk8EqqXjKHEltUUt!!>Ig8`1!wrENB$DNSpmzSb5q77n=s>KjOL9)RK31IrG7^o)Z> zh!vyO=5F9D+BYE=R&%ks)ID1TMS>UVyxYk_unYZ{@$0 zPx3qZ|AbG}AE$^?H^t}ud#F|X;8+YP=HVd06}4sIdc!Ot$T@ER-TV8M4TRpM!EC^m z-CR=HmqC^inW!>Oz3o!f%UJb%JdsPb?DJyftKI+@S3zHtL6&sNCXDmbXMam|{D3JB zqLkZOa~oSvBo-ZY8d`Y*tDW zb5!31a?$pF z_Ty@l>PJU?=CP?lR4Hd74lf2$k5`C+7X7w%^#S@|;Zp##Hu**hoo&B>h zg}P)kwvA+Q_Ft{7qB`Wzxtq+VBQ2=(df>gZ_ElRBF;|LKY*xxx9a?h^eSStiKWB{h zD7VC|w-(Uo(r`&m^tF>#&C+DL8A8asJHELy`(PtZ!6ib;ljN9u&}azEGYvak=8g<{mDN|>y({XFU}3ww>S z{FeXz`Bz^7Sg&=OwG4w~>vdYD`9h>_V=q(fZDFoCl;AU{WUxd}=f&?_HP-8-YHf@B zAC%w1C*S*Fp3M&_siMUVg)xJk1gcbmDxEnG&k#b2NUL6?RSGft!j`Uq z7AlpN$Wjh@fT1~NS|7j;rB+j_#HLnJZc>5|i~isXs7=kI2l`EI@2_16rI9a}R^rm$ zKZTkzIyH-;7=(=FKn+GvuOv*AIxjv3ZT*`i_*f-RU{-v!E$wxt=6}$3ojNqvw81qR znoD9^aJ%YPIa(=BMg}3Q4BJ6BU(xZLW$@lgss-C8aunjRM}KP-vbSqo#1*`oA1@%S z3XhkU`5$+Goc+4vdzZfoTG5RlJEaVT9KBgxt05a#a2EWv>z#<@fKDKbQ8xh@y|k{X zF10tKZu1y&E!L}538tmiAxfDWC}mdrs=WYiYFJsROD+Sm?DM2+okesB*ixbt zso3>GYEej<1GdSKUEj^@*OwIGQ&-=|pS$|wJg+a)cg2lptM)w3{)`2JZvdUrcS13v z216GmoK$vVl&v4MQ&kM3dtTUABOeFY!h_u}5_Cp7@mY4!M#DLrYTTSi9uC*;8;3;f z7Ivb+mt}1y^tCIiK_11|T{-9*LZi3P2>(;2VmTR`KJwPcL?&R?W%F`@oT%=w2VBo-e6`ARRQhfJyb&l@0K1G*+JrJ*YsEa zb=OYY+%|*581fK#qxG5<=~YCyJ~63FqbT_XVhfa5-5QHhWP_Wx1l`k-Q#t3Iu3^)n_j|%<6mdy1 z1y)_-R~YogGXP@nLk256?Ox>1FMon1b$oaEi!d3NPmL!}6K_8iF1Lw(WqkWLO`OE` zRqTbjYn5yi(&QCLB@m{7^ntMIAq|Mwu2`yLC#CLL)N~SISB$N6T&l4jr)#{^SGfTU zn9h>9Vj}7kR$&U*Y;!K6R;Z!cx*&6f*_(hh8sS-s8t-oI{$DKL%%9o*G2SX4B=*(} zM=d~cfpRSLt4dd$gcCYp7Nu*a<7y*Z?#iLr>rLv;Sj1Ib@~k5JN}Oh1F2BI)*oaAq zN3Lz>AjfP%3}PEihIVIeE6rl_DT`|XKrkr{HWK`KZc<-oL1>@Dfp8Pr>lFL{p156T9e6wJj*YWbZc;%Pxp^I8P%=_ob6}yB?g!sO zP)dPnhQxL?E9UCbdKmv4a8p91^#cwesOi8w;JP_kvjaCw1eqEKA&I}WT3iVoJvxq! zI1J_jie)xwbjN$|9sq(+J6JVLSr>e|Rd#-pkyWcWPTMW7K&pl1=#>9y{G+`2dZzzJ ze~s7A1f3$eC_91o9|_;|e&h5-Lo$?OyKb!OLikf`(A?lkGN_Ttbya zJ6q;$m~t1UE-*4PU0lgBsr`#p0Nb)K)Kp@z*~G?tRYu$7IYrH6a*m-gLtH9M3&h|M zkkU?^C7_ady1dMvy82(6r}oeuz7lcxhTk;~;Tf%2QuO9Ho7IgAT5kXg z;V>Q0o5t6nL1E3CK`ZxD`~TM%+`}EH$uk%6J9TF_L86C9u|xl$X$@G~h7{)3_=~NV zao7l&Kuml@W8zwN-)tP_Vdi7N!(NolsE5x*TQ5l6OfQ%x>ec``5Rz8_CA;OE!+dML z>2V(1&faym7J}h@qENi*C>tYXuXc(Gq2&WC(42sK>V8I}3+aPp(y>z2DN?KBM!!~b zfm(2qRBq&T_1iH0zA%D`o6;Vd^6nZ?b;)ulV8p1v8zd~ zsxvb07wR0*&LeH>uHW_Xbhs7p~ z>}9Bv#xxbRIhbTMDVp0IPyEgmOtC>&iV?+_!V!OA`v>?r`)-bErVfw?Z$u4KB_=`F zke5QYPpnrynmdV*GVH4dpv{GHl4d5;ufFA9IlmnEZMNUoi#)7Hs z{;%z7ama2fc2j}y6@PANSC(GB;=0my)2X)W(jkPjO$4O<;Guue%toRv!VzuKhr>9r zeFxVAYjH)XH#{r!M$N4U5$&KWq756a0h)(f3elZ<5)f|WcO6LJX0o& zwH2<$%94%oT-gtM>~^>w$I4F8VuV}j`|JcmZ%(XUD`8uyp<)7E_6BPSO1Y}^6zb+S zU;fTN%KK8~g*W~tANhvN$G#Z+B4)tKKQr4Zw)Xd70{LQ`%d((L zNML;snX@wJh7}9zaZRr(F;4$<5zs&X6#&S0wN|yIR+(y%aVgAo$%{$MNhlI0E1eN` zO*|r%as_cP>fG_y>ksnx_%}FOny=e%5Motqtz>baUxXYglVpkt`7&aqvU>al-aOy)>?E>&CLBMmoZL_7BrLJAIr4O&bYz6iNEy21 zfYZ=uXIupwEk4hw|2L@vgK9Cbh*u1)o{x z<$Cv!tZwS*eF1wB*W$gSwT8pt#MSF526J1aUAy1s_G=9{N7EtD<$9UvO_$%=Dhkcv z+0f+v=Uc0U+V6`8!cf~xme78$_kOH*sbMLu3JqPoE;w4x)v3|NW4b(`M6dgxWS`X3 zzEv#6(b+<2Nl2}FYgeyYnuMY4Z#6r$cz+()&Vj27;rx;E?9Iq{9=W&>-n|t1sj^3z z6n4cJ_X~MzJbFLKEw89z2T}_o0l5;oqt;Lal6sR>64W_)UuwO$nz8sHunn;8GUbK4 zy!q?@2p@km^X*4}jc_+$x%wz~1RdHS1tnCa4nkN!*MjYw6&X^8bRCPGPX#3OA(go- zxk^e!hNWW@vmJ*^ZflU|zw_bvZ~hOD?5o}Y?7dX;{XA7EJ29??5;Do8S`>=~ zvbP1%>PVzrcI#x#{O#qp^JDxVrU5C&6d|r4E=pZ_^m0sw%t~Gf!@5c_oy6rEW5|ow<1Ji~Q7UD>U@1l5ndlBvl6BA{N#mu%bzHyB5Ha zoK_>TqT&>yBa7^D5k?d^ZJlBybF_{eN60H2SuV~!W;$Q1{_;wp@ zrqr9}m>lfdty_N>+vP)*;(Y=;G}m%&xoxdFDfKHRClR`KMd(_oV6GA@ELck$*5vJi zVmH!;5?YmI+*~m@^kmA-4!j(o1pYb??SyM;d4@6yb5_nD2QHomF3%!QF9K&z1846U zF$bnB=ptO~jaj@P>NL`&>g>l+7}PYAg&?wUY^&Y#86q8 zQikByLTOW#-mqPD_=_sKsw`TVmKXU6{umE0CqD7+|K@n)*)7B2o}gJ+Mq^2W)PQvn za%9j*tQ|EaEGg4P`K7C=|GN_P-DTECDeAk+!qX+yvmmld@9n1H7W*a3l8*jGnt;Hs z{)0bL{*NE}=(*g=uP;xmbPtZcee=?t@70UBlkO^JjX}3U(Cp0e5K%^c`ux}PSH|B< zS*;MQ=&{lTYfzy;N`fXMq8xWdiQb9rI@sjqIBp~G5}R~0JNUzri$9ig$0Nz;wWZh& zIsY<&9t}ztjb0)#dRcZF2KpEY5&Fqhgcc%Qj>KXP3lXE1O0R*815lDe8kN=Dxv<3o zqZUF6?4%=vo>`4u@W#?qX2#2rxj+{yoy^P<*^b^oB6uk|Btu%Z%47lSE3yxab>X$2 zDGV=UUi=jk-}tRtZawr((WI%z4r4j-D!_(-&F0Omol=WeDMf`m33YP6Mp=w9s%!Zd zKcz!#*sf!vKN8YlL{maaH$9T%6_Kyfip>RLMa1LEtonG0V2-=Xe&5g9S_*bJp(|xn zZ;h;RQ%gDcOT1@sT^TG++R2kpvocM>d>)yeD_0kh{W~2OSHg7Jaeh`EYH9(E3CnQ1 ziKt%MM5exSM+z6q#J(C`HlBydepaqZCRbx?#pCVSwM|#38>Oth;bWPas0#zK63JMgY->}i>}{MY~FFV?RK66`Dgx6i@i za}(<_VOKBiNm_^1zV}wVp+n=NtIy5fPT#;^t$&a+d+5{|b(C>$fm{tul@KFQ#IJ|R zORI7FSU1C{*?lYYfrj4TKiiomYF39$rxO+ZJ@V;Fwh^}MphA- zE~w_YbMtV;GH2qvu%wPiPYs1B%nUIy41HS>5$pEkQHe3YCSjX_{cg{D&(C@L?+!fr z*@1`OP|fWAjw-hv2uGbaO5$MjD?^43SuOM-5U5BpGR8VpQi8ZLv~Qv?aTR9` zEpgm@L$c~(uDpfiGO%ownhSa9*zeX%TPTw<&6V9{;Q4z(TwD~hWTlu8va*>w(g0l- zd39Zhy&`#G65sIaSb>2g$}Sc%mGL|=YGE>CDGOy$_KUEq)jbAMiPKX`$VlnvS|c*= zjL;QAP_no<&DQ1(#>ohqLRUb|s8ss6kfw=wtms@Ay63Fz8FRkkPM-P9`ZsW~e2{e+ z>5lgt={YKA#P#0#8p=8stRri+xn9k))w;8^y;^qiyh_NMdnXUixAS{cOc$eusxfHz zpMTFs?FatkKe4ar2CyABA)d_fILzH{;^{Kw=Yjqq%S0$%-`O0nm>K1Wzp?y2-dKH% zUJVOg)}-FmZ&8GJRJ=S~gy9HM52p=g8-S^EzjQXg;~nh7tYM(ATPkyG;UBfYi6IHP zci%zh3u16vY3L%u8rCYrz9U7YPr|UTlw_C&N>YYktZGC^9B+gYjIW!CC=G|Q+|HZd}j z*%#%uLS0o>t4ipN5Fs8H>X1PLM?ooMq`<|6aCvErXTt6>P(;wZG3Aaq6y{u!8VC}& zvre4G%BqW;rbJwIls>YmLP$M%UMMCEClQsv?(B-~lV{#c)kIfT1cPBH6bZbz7?hFA z-N=yPTq;IznFcVKqWcSU&ahVM-UxBQNR%m1W@jbjBjtFgEHjKEq$qUO#+)l5%!#Yc z2q%l*YNicyF057s8I66t&ub^gyf{7M_WBn{GBM;0p#)<;OFaoSEY*!ui1zW8{R6-6UzHbTRMQmB%GK)De!bc=td=29(^wv_ z?u3VS(Rrz~7!rkIfxol-JN)eaHxc?au3H4{6j5W;LLVZrbK>l#cX!`WhHlel`-kYJ z=tV_6V3n(fEfn(v)^KIa=iW^Y+v3qv+qYnukqD|C>K-cYM6jUrA<&12u0YH~Lg$iM zg+yfq3a(v6JynR6*3-wr- zB{Sz|<%j?PAOJ~3K~#)FjT5@5bg5$qYeGrnxW!5!ZCA)LW4AV#cBIvYT1Ub%k|yUF z*5m@8qa{(r2rF;K=`e6BDQW`i9_a(JjWA5CG;p==ee@qDI#p6!fiBc3acqGYI&9r> zG-np+*{&vRoSCyT0iqR_B~S|7Kkg`5Fd78Y`G{8$KvTE%KbC9o}}|MumN^MUYl zl$Z!BRg;7+QOz`lA$9b}8(j^z*2gP*^47F_^11VOSHh#MhKrIyt|1j_SM#OVZ~Np= z+Sg@%k&eax+^wTZtfUz~n5e~W*YrBB4M zvaCTxT^q6zYKZis&=qearylMLgbuo@EYW?>rKw5xjnTifUk{7VVQY0Zyc{XxSrfY~ zf?d4HWQ8LQ+zW6V3wKkbOOd%6#|l#^%sLSB#9SvjQ=(?#;P42^kt7|mQ4&|gOOK{j z=?L0W%7Wag*m>geokwh!J?wVG9O!Q!)9b*>6j^8TodL5<)|o1iXe+vOOdNV-Dum&- zkD2Bz@%=B+zw$EMx4z8&(KAZjvfVGlsK}xWws4hw9Ax`SoC3D$I3+T~0a^LOEh)j2 zkT6hLuvMWnwDeju--=@6f>; zoJkT(-Z5uo+U?j~?wN}q%R(Ls>t&$tj?mzEI7%W|X1ai>%We_SObVG=A|(p3X4a`^ z=zCU2N67!n+ndH}dY*@Q*ZnN-@~vk-Gs9U(iWFCEmSkCr?bwp-#8FVkb>J>>5~oG# z0C5%+K~l7h(X?n?APJJ#C|aOsQnW#eI7LyoO`F(G;VQOFc{#>Ip2G~_j+9|DD9BcLM%z4#v6y|4voT?f+&jMdVK2X+8*%< zQ)-g3Brl{Y61t2^@)9^ro+f53ToGXH11lZrLe7*{enXHBDu9Or6oT;<-ULK20O{+|soasVYIw?%>y-MapzI|%2i(fzWH~v`y_(%Wo z$5T_5v51vBK1;W*Y@5aq>zEQsc~0F`{*U-q=-44xk1lhh6c42pLNAmfA&hffXls}j zgE_dmpeYMWn^*zsHZSj}VVzU##r=pP66q!7gPe8Bc9!HRmv=EKU`>HiLWQD8Sy$dG zSVcvVJYHM|Xo_IOU{#645~~Z;%ur%-N8fMZONEmB_AOLLNFD3@Ef3E&`8@Q>Hma^^ z?`$x49XIy$N(P#8p}*rbr;p!8@NLs_E_3W}Y_2&2$`wY_Zw6^ zA#y!W9_oN{7C%>vz2x&=3sw?cm%p`jna7Xbz%&kucLz(IapzSbxb?7eQ6yAK^gTG2 zcsYESe>(e5`B&wyu@#OGW%1Jjl@yE>Nn11poAbC{o~0A?gpHIEt0bitwb@u5YNvH2 z`oI0@kHtUzbD#e9_5gnVXMWtQeWoRe&M}?Um{r8+Kw%Y? zQcOn^iunZX1l2@jKB0&K7d*~vP(Gkzm8rE|M1?>I6~QS~(Ss>4xZP&rNwUVpi&}9OOg#bIK1wN&L9+6TcYNgbS~&ofoZ37Wq@^oDu;cLCU5(Mpdb~< z$fKRcR-Q^L5;f5VYL(FY6EG3oM4}HUt4Wnc%ZSvS6I@G_i1;+H0}^WGh_sxoTNbg& z*QZ?|s2+^aG_dSE8`p4a)v*pSi&rUFhlEPdxQGivK;^*Q923gniZp^-W=?;aY4X9*C|P0^P_04@n`dEIk25NMh9C8RgOOR} z&gsy9K^bDHIDP2fSe)@CYvdKvhc{fM@1M11weEBuB>HKgg54y(?Nfj>pUEah>lQ_k z=n7NT{Yg-Fr(tnfD#w@gC;6QJQ5H@Sv}V$04|?hfFd((y4UAf-a^H(>3$+ofWKg9D zEG2Oog%lF&!EG5Yv|)WBh{u|UBahpBku}O0kaN!19boCyY>z$%hks(v3W!Crfexi(=O>%WIC-VlcrdbKY67`?^kG7;qR_9Lq0}A zCq$bd6lihWMqRaazXIXVArqvg_$WUrhAJGwHl!zNpW#XmuNoMPgPq?3@s5Ycp@?si-TdTB+?$y;u z-A=uKqm1bm8#(={|MHiAS5na5Qvm4tSrnXeJLA^-)G95_YnycIhW78hXWprQRsJlS zSYcGa#6&My+Ch?x0;{qwu`pz#O9hisG1ZEWoMLxDD26@GbW!&Y0@e7|ZnsbzrGIjk5u9WXx6hnrec)rM+ZVpWYU z3d${EeE2L$m$dh9lU6p@fSrQEa@=>AD|2Q~T%ocxMwb{ygaSs>p6S&cZhhfv?A?5c z-R(nyvBa>(Z9J)NiG9Kp71EC}tAIamIDK%!!{s?!Pu$?zcf5XgG_8(*Gu?IYQ z?JoNVSD37zXf#ngrZ;HovaPqOu=Nh3?L+MLB~%IhqjTKi5n*;Qu)RxrujA~_1JI`7*6Ol9P->Nz zB#RClf{Q||1RwI5r(4B*sv+4z~+xM#V*>4m-y}M3_NOH`)X6=RE4v^545#Y*X zLXxg?8ef@AS}hfnA~cdgnqANs$s&egxa*E&T52#k8)_5y#*_MdDHglTZIk62Ec-Q= zW_vvU+>7k*U#2=xoSok1)i1qF@|s#ldK0NJRH8AGfuFHWEQ&S7oh75z0&D7L=GeG} zYdUHjNkznU=QLelI-f8uM<_GJmR;ui2}G6HI^5@_b>Pldzlq;ELaHett?*@oVuVOV zj9@1YJE`f;1CN>&&8*~^4?WLp?=eIPc!#Yb#qNZ&WO;b=bq?z-%%mcw4lViXj>%JQ z)r_t`kDgoB$9GvRmh_t=VzWR(hpY_AR0JAQG86|j)5o92^&S12w_sAD+m2W{s4ZqZ zX1xCto70|KpZ*lbrzfN~&}c{Sp4d1l>zEun=54~LNHw13nZD{VI#E&qGIu6^SU}8pxZ4%TXd?Eg8%+om^b^j1CIWt+r^l0hE$HBI#?Lvwdo0oqO z0U$2-l6S5%F0I;w(YZ6#`P%QD{FeDxds2J=@wpZXE>m(#1C`ASJVrstJ_EM3fYBTj zib_TLs0k|9U5|96ZS!2UySR06!+nVXog$kQvpS4?KOUkZ;Yk}I9=}TRj@`p&7}*_S z5Qduflae)(lqKGFxF)CO-fo0OP!inF7Z`}ghkVEPjAk>80&5$rHt51+LJu1buI(e0<<6rM#;!%CBm8oM8Y{*rkP1!Q1YFd( zxa97=+uS=nWB0{pIe7dDWPSyqN4Mu74WolSm{lwv9dr2j6jP3g=LV%aln1>%r+)mM ztk3SU{K~gDxqr-Jy&{AjB@q{(H=3C!sut;zwu{>|Wbr@6uyTE^kp!Cp2ek&W@KXUwe~#56?&fhnF<2-Qc{#Zcix>3e3Tr z-oeAy?$A7VkVQoshfyB2rHJN`R4(XOo?>F5GT6xhX7@V1ihT1Q{Q@^1+(h=a*?#e9 zw&w=72;6=74c7PX@$BA|*<^~O$gMB^2H$+`Hurr?dzO!)+T@sAnsNPo&oMciQ%nm= zy^V>6qVAdP?a{hK?;MSfv|fhElP5MusKGuJ`-Jh4qyoVUBe9wH7$UZh^u`jDfXQip z=`x{u8uHn&De`9XH0IH^oHr~ zyVoi6Kxt)E2SzFL^UhC#F~4e>{EeQlr43nGfr` zU76QEE6L^VV3)>Qjj@7NnnENWJPaefMuajcjtPVS-N2qS1M5P^ycy=*pj`F|ufcmE zxj={!&fmn=V-BY^T5D1TcHD9G>Xgx}Vs*NqL{a)gt3dg{qmU@WhRGAV>|L2rYRl=% zcX)K?4mZxv*sd0gFC8%1tubi4kBqhps_hC@SnPP4Vj_9pT^amlhsmMi{Xg&#zW9ru z;f>RVOI={;6E<4Px}jWekfb<2xyPILkGXq%g6vIr@r7p@A6`dIX5bn$EuvtyRio;H zWO|ZKND;8Jindwc+aqkB=wACW$G2bQ=E*7Nx}e(MVp{Dnxjg66)|6tddGOjj9)0Oe zl<%p}Hq^J?MDG<@rn*_<7sqHjMwuB&IX?fz&vCLosEh{>R~xPd zNAvtU_}1sX&b=?ZN@^pjQdDI@l7h{mcs<5`K`swj6gGZ|4AkVYD<3n*)jx`>MbpYl||r9t$$ zIl}uDdV8SptPLDMSp>qlMzm0tkb=%giD3%ROU6C)WN7x-!p7%vz*Nwz1fO&!S}zi% z$#)K&NmM$~tGpuKrJB!#KgW)3xuJf&dCfiZ#%VQbeVnzn!>jR0bbj*(lK}uM##>g@ zbfWumYjk+&gX}%|@h)iX)qs&RiADykb{J%#{z3sROst@lUKlNqYYQYWbn6G;pzeNZ=kKzKO$E2!9 zO)X|L!c-b5dy*HzNFl!9g^#_LdOqQ^|M-`v&sxw0ZHk<%J*Gc~23|jXgc(mb+`h`r zGuPR<^f)p)MC=HoL54c9s%z9p6KqeSBd#@lSh9HdAdm0bhO>M3dAT`bd1H?ceE0)A z_v}+tWsR+-=nxQ=^zXHN(SC~C|Lk`t)d`boiYoUBaYX0OY0uZ#sSr-y%i$qV26Jxr$i(4GT5-uIwu%xFeYwcL2$lid8)n;ajl*x#QK=9*^HaQ6CL?w_^D zcFmRdJjL$SUB>&{NGiGimDhRgb6?`sPyaUWIK0lbZ|NChPdwfo^Tw-R=k@aiyPtT9 zC*J=w6SIf-g!g0m#u3W}m*26^H@^8MN6Qmp1rIyV=$S*__0eY-kN2^rr0SO})*HM8 zYM&@dp%@jQOMDlQ)MdxQkiG}eS&s(zc1>~)?KEkU%~SRv6cdH3GQ7pLDrbL%knC_c z8FL1^=`%8{9!$YoDnoKk9c-dtM3J^5F)ECB#3w=lw#(ztkxh(L&FA=YtoqU7Vc0)e zD(wpyhh}6#RoWQCA5Z}JtN-E8N!wZLW_5usFJC>l^v9HxV;6GcL<_hmjI1IIjgR48 zj6xJMs~DpxQr@>OY;J@%F(3Sd02`g?Le^Qe`CceX6e7eXV!FKW(?tkHBK3*5NrX-# z=Z`S$1LjxXK{3@7Sdy->Mp19?^2`Tb;ETWc1=_Z!OZnQ5B$Sgek3D~ho&Acft4~nS z($qcskB)imGvA`nEt~d;RGc9}vF;qx`7Go0N`=g;Oy^Z&RMAj`iqww?6+HFbJNPE@ zng8K`<%)4c-?Kh*%*%qs%F|ui=f#h|o2nXS?xjKL;p#8h3qU;OxMEb*H0zf0+iT2d zgL6H7+f$EgR;lG1XG_eBkMTVpdmqoe@GRA2dT~KDKu8p2Wq9ht&-3!9zQnRUW8KV% zrvdMT_3}-Y{R({^=;`_GTgP1g;Pbru`+tbZ{?*}bH@oGG5_IYbriN%3Z^3wHo7ID3 z4oyvHgvId#?i{V)>Nd~)q3c|F`W?*1yO_E{#l+s>A=lphPJa2H|0=)v8(-nQyIUMy zwYb%i*I)k@kNk>jAAX*zPrtyt+D42AKPJTuNjs#sl)H1rkIz|r;gkwR?;`V2MNw23 zDHzoWTUSgcWBT<9Wjaiyp(yhOk8!vZD72t3MABQ7vzIY>^hSywD))m3Hw49Jj3*ce%0ks6Adq)Epabk!BdNxCN3sb!QrMlESNe{9 z-?Ch;czC*IcKtEl^NIIx^|?ce*>>h7NCmD#Y{T}AeZKdPeJ}sZ{Zqbv^A0=PC9BSG z_s%(&KlvO_z2{wQ&#$0#mv_PI68w@5hs1DKLSwQn(o?pAUdal}C4- zi+T}T9NIDGnXcDA;d zPUh%3cWcZP4ytQhef~PX`sz!3)wgshqP3zhiuXO;(WFF(H37lK?9>yLbx@V^w4#t; zFrzW=|L6z#pTGP%p^e}ZZRgR4J6wO}Dmyz9&Q~qT6xgan5l~VL_wShvt+gjjHLVTk zCLgc3Dsp=fxMLENt6O~Rd!A)`Yereb+;tVn0R%wJa~IVIOgZMtQ`fos@=eyKJyv2S zkdXzYedoEo4E(^q`2$>g{zWLK1CG2Ih^?ax=tRWzO`6O0o&9q8Q&#a6++QNhb^oG{XwX*tG3izr8kCBbNt?=hyvs1g+u;sQY| zDUMm5Zb;D+Vk8dkL(j!nt|$2=Q41<1bPv)c(#+$NqVzSt@;6}6;yt?xWP(0uXE?$leO1VtMNur zOCH~)frcdlO@h|v&A$$z4;h$iLjJQ1a?D@oMn~EJag*t{vGjE7kkw3~B|iKbN9SkU zU$(qsH&V8M5 z+&NToyzlxIu3f!~9@S8eKsJ=4F+t_j$EX4L5gU}T)Uz3liim+eCeC`nzV9+W^qucz zcjpRo?J4vIRm=w$TgrG^9rNr}mB0cBRI@P-gLjrr`^>xZidaVOE;j5uagFzW&v!vN z9xk&Sm^MH77eo$S4Op@Qw>-w5tSEfqXz94|ktg}iPkx-o4j;po8NO&^N01SSCRm%B zWqlyU4LgtBpt`cdotqCCk4mn+c#Xp+u3+jZDr&4&h!0>gNIx_!Dy<2d4ON%8b~xje zZ#={*O=mQHT_ABqY9h*JJerz=PiB3+jc<#-sh|HP zyNsiqTIt8HUON2Kd*jhlX9;>DLbl%aDnGc3;ha*doCP5H`ffYqx+s~vo~vX2$E-b^ z_R!-|F`!eT7+|+uxQJTw_f=Qk7(Ewk8{+O zs5c^C`0Q7B>7}n`RF`D#T}W_vd7Dv8SmiKQqwFj%8YG3P=Ul$=4t5{g;qK|16d9C{ zN71H)*MZIYi0RH{@?D$CSwIBwj>33?sfbQ7-O|{Dnmey-m>a{$Sgt*Pg=$uzREa6J zNO6?^EBbAKn+%-2SYyjE>$RsvvlLI-+TwdZ_)*^dv5!+#yDX1x(H?(&Kvmg+i)9CB zh{^$=7(-lO>JhC^jD3emkv@82RJ0q-%dO{!{*~`zba0rrx5PkPEW5_{SsYqgji56XWk`2UO5u|2&I-#%%k%XMBu?CA#S&FFU9wB%FLRAMCd(>J` zQ;Y8*NTRlRl{ZNivnrbtCa>}|YZP1zeUhV;hIF_&uCW`?;Txq z$RPeOAxk!d%*<2b(WOT3@AJ~>SJ<_Y>jxty*AGZiA!de^Vbmcx)szcGm$uNaKu201 zxV!R*_N<)eh3B8-+S5<5d+7;MQn>aZ?refJCS$3Hx!EP7fz(Re$2V>s%$G@K^pLq|Z z?sLBY7;sI1A*PbVf)pA$zb2-N&}&AeA*jUeGuPO;^7!yQ3}_9;bf^F!Oo%#>Y(pO# zoQb4OkDghI+9EC7y?aEH78F4dd`YW2EE{a633@_G6I@!-E;@emQ{NzTZQctZ13h(! zsHpG~GTq3ZfbAhzVjpoXpp-?rM5u&11Y$2pr6_b3hq?hluOxFVPA$|1jME(0gh<4y zM9ilkY-ued6WXrBMNdkKWZFEci<*GT4Kr191%vxYA|TJu{EHhkfvVRGpblii(+lTry4O6tN;jHW~VuX7ER z+~CK$5Qe2MMKfCXwbOZ$S!FF+%qxVSPl?p0PEr&?&L~*e=zm zhNw|Nqk>1rT;l39q~@-qKesH`kwy}QC`x5e0!Mcra{HCn2p)Xz*euUEK5Kb&-|^`9 zA!nx#dHCR%PyO0&^Z75ojv!?DuX^jD6_ssPh(Z>R(2J1!1CodvO-uo`bd0)$F0%Jf z`Fy0-h5Ux8d~R}^H2lAVHbs^(mv>zutcI+(BsU6o#$ZQ6ED}Bno!6vNVe6E4D1u_u zLzKj~%+R*}^FRAvsBc>aa9oIqrQXJ=D>wEhpWGeQ?`n8kJ`)GR z>xkiQUqM}i^}?jm>=c4iIa93C+inSA;QYl5X>3Evs^l`Gzrx^e!w;X=WggJ#1i=SV zh;+&0lq2>I`eW4n-z220mXefLatEDXj_Mb%TzT8X9f7p&fOA|tX6e5Hgqfu}k~ZMai;R zF@J1IwPi_qkeUQgF=3J+rhp!te&`C^1W2538tyk9t%Yh_aIk-cqS`{lkb(!V%=qCml)5{s%QGtQ+)8_-!lM1i?`KdR9Tvr2BC-= zjx!?o=y1)NgDaPL>LVXvw7r+Jh9uyZ!w-89jK~5)fustfdQ?^8)``ZiQKOPK9Tej| zw61dFO<8NVFh>-dys<-YTd(1t<+kX-ou33f~5P>HDoXAx7u>(MAbQ8n z_ME+g9Zrr;x%tL@=p+45Z<&-8bU_kAdW)W_*XQ`K0xZrYY)peqEz!CB);3DfTTpdG zf~M?p!bO#{UO$wcQ4+1vGzi;PF*Aup^vqPEZS%>D(y(e2qB4Y}S9zAGJe*Yt6%rM~ zW)qptrti9Xb?3)!-B~RAzK+(%_;3H!f4DwRr|}p5)?fMmcMhydL8E+8m6xv`jDN5J z8M(aWwDwsHvl>wINpelU61ZAuO7dv190ZM44<3}Pj~(X`;c99q{Pcue3pBbOHA);N?Y6wQ49!&nhKeJ9qr#CqKz#Ydb^l zr5K{91>I!*ZEA;1V(?vSMGTtdsbKc5Fh97GcV3weP<{{L{B7cJnxff|#1Ldc@DH=v zJxy6I?{jPIu=CwaI**&T-onYXL<^A-i9jDZ(q=_TL90FIj~u#lhzNmzUn{=;`8S9$ z(ZwE@0?|iS56*e@<=bebNm|}AJYPVOGfOC;B{y2N0_7LPc0(E+WY5LK5o?7XWqE4w zX^<`{XjCqNi~KMb1F%^q=tEu(5;B##k2%0ttq~pAwTWebM;=rqZ!OZ4L<*zmi;&rk zqOvcRh*Ba?K6T{>m(9b|lRL|Q(U6|k^gQnWDje}^ZyQT zDPer>8`L4gKe}}$-#QnOG7=QD0YZup0%hsxmY&{s$gN*Pxdx@wTW${-XxSH{-wU(v z#Uqu`_rjwGYi@q^gz;pLx@hTEp4M+z`5qMS;>?%X_P96P3!Fq>2;?*_4tLsB4wKEEj4 z3en|Ipt+&uR)~&hojr%!TN9=`6=iAP>dKeJbQn746dP4Qe?Evq1~qNkK-y4^M!XRd zuiQOiXEdgBj`x4!`}mIU|5y$h$>&e5D)M(!mB9Ji!NlkDZGy)4J*OvUY+c@^noI_2 zi+~;H1CW^a<4GMTkEkqD^7&+$DdoAS^j34O}o)H(@XbjHz<4LYR=%^<7I5YIssmM)ZPc@13&D8E8j z4%Vl92JIe3m?zXUPy|CT36nCdS_bvFG6OBx^O8dszz%73VPRJ*qEQ5u7-?Z7 zIqK;F{^15|ROj-1)Jqy{uLI_OFue2@f)kQU_%6|PiLed?C&W#{6_O+G;sM|0_T z(ZiI1{B@ZNrzZK$f8o(I!wbpxj?aAhYrJ{?lzKAa?4;r7;TgU2RFWNhi}MXeNe(O; zlq6zQeDmw~IqDlOKfOze8h6jrhmP@;35UCv*g6<7FQ?dvVsYB@Pyfj;;eBAQ)I4?R z5N#?#(ga-)yEWQ(d2Hx9v|VAa1Mb^E5aOz*67Wjcn~a&yZ59p5AkkDs-n+(ts`CmZ z2Hg1|2OVZt2-PSu+8c9wh|!;UD`1)wqDZeS7+#;{~{X$V3K-$VDC(9Zk1n znNGQ}cMV%ia>kGb2|=o}2RrGE%!zqfB*m6?ea5=o(CHT61Rgy&Mi(_jS!IfbE{V~R zq9vrfT6&j$>8dnHM>qu2!dHV2*{=?t+ z%7fR{d~|AxNi#HX{=Wr)Kk<`)Q>ue4-HRUU+8p?zzE*ql&gX9I{6rb;{5a%2{6cb? ze(_)>$<~v?C>onM7tJ^+qR*)BPGF(mc105N*59#!q(Ieq&Pj9^CaN-LnIo5IbwFaI zZ6Txp;!w)tOdu=+u8&+j{|x8hE=yFd^9KbT7rJ|ugHCzjTO4{4F>rB-&T7%|(r>>; zOldH9DU3j;4N){^XcB1!Iwi^kNku}6eDfO*_}0shGB3eJdLK|qF{{2oF)Gl;fJ8RU zhQ+D_NmRzLdpIR&g~W`uc700<4Z#EmCB~Uy2YLu+Do`4ogIh}MZqKOd$&gw%B)_5W z&rw*cHTeM&4GeE{$|1sb5FOeG)A=k*Hhp0K@&Qjj`{EEFF0@{Q2q3te6%4rST<;T`wTA}V0xOzhG9TqMMYE^*Ee*|(YHM+2*(dL_--H>OD?&R z5@NqZ+EZd`=|W_&*wCClAf}$W6kh-GIVYzpY$1peLQqr^=@67wOhN{aZphvBO25sR zkd%p3n+vDuP!jZU;8l_p^?h^7MtPJikScHc$XP;mBi<%TQ83ZC5@=Mc{iBSiSV!n=6T1Z-vV&t@l6op1dMUs4uEJefx zQP-|)|Iz!$i_dhed+1x+{`i0Jk6XLig#Z5U{#)VyH2~=8zK-SAxE)Oo>NvX5dHeWd zd)ptmJf1z@r0k6(L>!7P<;HSlbHgGS(3044ny3|C3)>3HGJlgdVfcn>SOhZVr-$=i z5y)c@)#Y&2^|{fkQzS_sX`v+1xJbVa#AP7FL^$(Qe#sv{_?O&#Jn_GM{cVMvx_J2v zx!?VgDV5O0%z2yYynnuw+_TV< z8)K_YhuduMQKMDF4$(-dgfA+_vqNIv<2WO=8$!24R7>;~LPs*i+ZI#RfJC-;r?~`3 z!p_c=QEkAT0S32P(k_p%#SSKEM4Oy)GgxXwaw(vOtt~Xl%(4I_3fG>v!F)a*ntXmp z`OWaKJMhCzwrU|rhMb0uwo9Bp=$Y3e=6icX<8UZl-kKH+_1A^QCker=Xd6%Ldz6CJ zddUEqr`=MRth)>mGqO_EEbpdlstn745@ zDG(!=6e%!xmEW=#%EDp4CO4;}CJDsh?<9dj3&z5w;w~?z3^OUt6>h9C2QG({4fL}_ zu(- z>(;(rpGE`lXaD*?5RcJLCPfURs;^{Zt=W3=^8CBHN)?MfN1;}Pc2Lxp=<iw865>*a7<$zO*AunVY{eM&24~Fdsm>5t=@K_WPpAwa5 zTuP)AvBQCgS5PFOO$sfEG6^nPObm>)C#BpIiHU5Gjb<=y>HHisyk(4{E;YeKLENseNcm`CxyHR5Zkwehau*=-FH1FZ$4uCV9I1VyVzbD z`VIZ?JG?D0^<$Da`o5#xoZ&i$kB+aue4FEkXP^=f-#q5plM1mN(XHsa4KV~-=Qz55 z!lQdD-njXY)5VHgU%1K1$vN8Qz?)K{Nr_q#1sWR@JrS2QTEA^xS7{I!YmM@WB6_@n z5LC|e$V+J!#ft}u!|5YlS$LGum@SPIkq{MWlL%En2ZJ*{U-AV&1$<%h^=izOSy$$9 zu8NBDGO%rgs5FfNn*@VFR07kZ^S%*OaMb3em5I4=-2rN&(Gsyb(iV~0Ms%Uro^8ML z^6uW|X50OaUKC?XH%8Z{muSZ7Jej2XARE_oA;wa20Qhfy_9qk2{n+3BKaZp?mr2R- zrSbODyYu?`sSj*Ag(25ceUaasx*SyY8uk;EMpG0y5L^gvTMwg@v(Y|572(Li(kIqL zjLsbSU`jAhOV9eg z-}4S@t-bdd?%adAZ>tCOBwCG-kdOtEkRpr#ffQqdV+sg{Bvtv~a^k9_iVvw&l1f}o zsz{uWRE2W6a2yQ57&FI!kU$7E0)e_)tya&s=f3kj=j^@L@V?KJ56?PRPT7^pr>^Sh zp0oE_@B2Lek&k{`zoQ>upf@yU`9q}{2{Qj%A87MK}Tx0o46*Dvzo^RM!*_q~&l=4IQ=N4)8p|FxQ* z@KI+LA)~!vwIdbfsaM|O*FX1l$}|yz@#QDJ%Dcbg{p13}v_{In_QqBI;!mICFaG#> zF1~q%E7vwut&D1ZOIM+YAf`~AevTgPNi;(-su^KkO^(Z#rB)|2R46uQSmKjhrgCx_ z_~1Jdo5kyNHc`{kl{OM+jsnstwW-KaBrb$z5+npz*v;z1G-F_Wg_Mj=DjO4|CL{_1 zoD6WH!jyzTBAprsQdz3MH&cW$K{dgGp=0$5IE=$0tYhF@HI^AU_m1eDem2KZugT#Lo2E*XGf{x zVusZCB-z*FT6-bKK*X4$5OI~?!nkScon|~>oO!58D?>H^Fr$MV)!a^;HL-{jJ^nCB zGcjFL>Q<;JF%`INc$!E0FJr-IvhnCGkry5e{Lxn`={P@degRwg#?P_BU;JsdX)Yp! z5d1|~BgX22CGn)kt6WR;bUPXtqzHp`px;@@==9@gt7j$K_T{9I2iuJf#+p0&?*lOP6^&3sXF@P27 zC>Snze(m))dGXoT__mL{lh8Etfl)z^`~dI~3(79oc7D=!ux3eGG`#xsWq$paA7g#- z2Fn!4M85dBuktPL{ygt|^dY9Ha`lzB`2FAhL;muMPh(qSL*b|>OJFYuBSI3R2LHm_ zP+gjCFySNFR27rp?2ou@qu_`0WX>`L4HT3KS30&K@~!tKPMr~K^Cmm#GFQW%CopX) zqJgrL=oa&NxdH2pI0|hQtex%bGjvi$$PyTnAY()t!=_nsF}JGwfR!Lu8Zow23A?Z} zITW+S&>(E5K%14?D6twsedm*}T>3oQ(Erju_<{ca7Yp#iKl7P( zFixM?-~EAhfB9|Os!Y*=h<5N7^+;i5uI*Tu2hqkXXc9V{_M339gXp7poLj07M(D@D zpvE*-ANSSEUmbWcZ1go_>SyJkD6$n)3=I=y_N2de`Bcq~u)r#G{F~E*Y;} zbQM>^zwG1A_%sWUg8b`6xNgxDsdHLupe0aDNTOtktOYtE!34#aO7Xyx5IrnbK%=mj zLBw7Z^=e0w1QsF=8WI@|u3kFefBqkSg_GxY83*OfH(ul7l{NQ1bSEG9_J>(@@VU=F z&7b|n3sec5-QPtL9BsDreetnUX0Fo|G*N4$=mr}%r2Y+ZY>;;0=##{o0wCzYMobor zWyC}%7~@!HnQ!#d^Z3y)_3}RJu?od1)dJ8k730FQ8*UsP(k^z~t*7b-z;R}qH1iBR zc@hTxV06pOiL)no>V?m8c;!0F+)|^Fv~cC(4Sw!_{O7#qJ$JKQ>~i7xS9$T7H>n0q z^m5oenVWY6axgloCs7#`^*E2}i#^r+Rt>>lvRJ%x(&p!2l6kBS>g$^t(Tum9ZFuDV zfLLKUUgQ>ifor^-m_5(GV&rJpA+R&2UQM%lI!BTj!yw4g|EyLaOv;cWT~tPiXmEV( zNZd1UBKd%}!I`uv3aL6`y)*f!x-EgWQ|b`7It5N-*k&aZ<4}x+33uMM_XDqN*1vUd zrTqT)|NYO6zxJPfSpPo{fWPrGzZY~!%b;@p!TtRojKucH+!;j?t{WUAyaP=kFJY&` zevT}2!o)KG>hTK~{Ff?ot509tPFPHbM`f${fX-^g|Ls>Hyl9ph6Ui~QqXSIXcrWj&Sv2QUrPpiW0(&Qi>d#TeXD zJgBg9Y@V5?1&0e9uxSK}8KW63E>liYDYJM4AkV3?V#cV32BjfjY9uw3i6@_V0r{Fg zT!PfX^V@(b5DzPgmi>T-m9IVZGGBlE1v<;DqoWeV{8_qubuHk)5|?DRPR|7^|61PGl$2SNJ%#PQGi5nqYpw>AHydJv{oqy%Qo_n zha-DUpl|S^tkj+8HS$aExrmcD28{`tT4}_q z#BT`f%<*B1#%1uK!cv41y)%IXS0?{hm$QP_h{WLW;$sQ464)jq24$QAIixe^Pw)Tm zS2z8iNn!I1H1^+e0DS*{`$sZJvnX9SdHZVjBfH(=U7L+DCa;zb<6IA~9^%2A)7J(! zDRlGcHhRY7%~Q5@T!!sjDZdqCti}OGo1qcMHVOS?D`VG+7L`aeMKN>kaO8n~YRLX3t?LzdPK~b_KOuYXs64+45_|5G@ zPG!Qo--jwl46IOWs)P`4DhV|xqdJgwT=PAdF;YDlxC&zwrs@wH_-Z6UNEjI(2diYn z3MS5OXaPZ4hQP**s?dmdb{zhB6*CU69LxfsIXNg!uCw1BQJXE(a70StXtzzSiIkZh z2_0faN=|#F01QW1?dRNeo5esI7!RQwFbx9-2Lr?UkmZh`nz;DdMP7OCO|Dawp5^fBnjnch!xWgX4Bj3* ze~{jc6F}!4!DDXW7~fF~jOK-F(b- zd9-}b^%tlA`$zwaFO;AEFaL`D+b4jYB%8FmIF)a`_s+fVJc4Eupw`N!5A-G+%{b5) z{R3V0uxx~rIFH!}-|?3-pDF^exTZQ0n5r>M6Wim-HF-#)&6@uX@lmb!HFXHaFcm5a zQPDw}lCW1_;=SQF5rZrh4T5PTn9;?`Y9V~;dn2!2H6HtOeCM``gn*flqA{A%MBm33 z%qcA<3 zgm57NnQvSxFvUa?Pdze(TJ@%&>DbFK>9NSk`08Ii$I;=y&T0jc+~T^uK^crdOG*Wi zBd0+mIE^PuKP*B;qOiBukj$ylTG!~fCZ_Bm4|dT{`f+aa88=Mh8-!qtn|)q+;Z=VB zH^0EkFI}OQz`y*zexC>Le~|MJ-#yEZ{d2o^^)jzK^D@so^A>;d2Vdlc7hj{Ul{!pJ zDHCII8gA}@u;9GBijit0h|VD^m8wDzpB!x#H%5GgJUlim(o!M-03ZNKL_t({%_zUl zLZ0JgM&?PBd1@HVSep^?EWkmHV#-*J+fN3*=h22JZj+9wU|TrDi!93lz3vipqP9?* zOce-Ae-^_SX_f)&V5j%*O!s_~+D>kmD+{5_dW*ISCHOzv&i$A&AIgW|<}wwQ3Lz9O z=1K}PR!{_+A}K*%g&g6;Hn8prDG9rhPoCf3{TrKR`^C}9_-_*iC4kZpG0RI!=gzj> zLv0)Admm+E@LQyDOEZ3OoRwI`0a}sCgLlA8BI_^s2m2R8wE3^ z9D{*s9I2}YV|4y>H1kkYuZCj~n9@9!N_4fE`hk&W6UpesM}E=Ix`nSi`8;3#^RM%v z54{&`m`gTB>avi!L~hCq{LOMFNgf6g&A;|qXnhbSg}{qXzQ~hb`~r8~eJ@SuS?nZY zJ~hjbg>f3VeEAAD-W+)1Paoq?zw{)pUA+PrF&WQ%<$3(_eXp8y63_p_P@0uU{$9gy1c^3X+U!N@Ec-Xadw!84Yxvm_{*wIf`fQ zCp)H^3oSwgf+{gacW%xPc~PI5#9RMd5UKv$1@%d9suRq#=y!jlePZO*? zbavk^aZ7!fm(s1@0K~F`SP}wd1U7-DDC{OSQAlYn71HBad#HmEMd?Cxa5zF2;p*Hg zun0cg9Lq8yhdEVe#p=M>@V=rix)U|a-Y3+!M5LUFs^C1OuIC0zhjr% z?zo-(ljjLkke)IMmoHu6Pygg`{_wM3fh0%{T)le8-~Z{K<(4z2x$Vvs?|ASYQgec- zKji4zhD#T(@XCePxPI{l*RO2|G13J=R2fVl3ePoSIj5kv^b1cbtXuWdp7@YM)|D82e>If>Arq!`#WzZhaP zO7;J*ML*ERd>^ms<7`A2El_7>swjNRyAmJ$K%~4jAj$Iq1w(t-U2M2_{3;jn`>B1U zIpLxs4FMaSX0;%M3ZlaFuQ5>}&285PtqPL`#^^y!aRvhM0%212XS)jyTJHteO&*?` z=dj(eIaab7N28K7QiE|lRNhvFXu?r8_ESE4_iZPC{4ZV_U)tpQ>PP?kf3^9{-}^56 ze;oiZC3c&gox4x(d{>Xr5F^p)bZk zofwm`uI3Tp%u;du7cWyq)^5Vktx-p%E(>MtNkGLwZR7*nf5z?2n@&Z}2}24r;((!K zK_x;{nHu4t_eB2vzXkv2&kO4#;YgJj{lis>>;=DB$I6^iEOa$dOW;5XZ5!D;wMX9% zT)c8fn!nIdmA3lLj3_Y#GTz+M8zk|VC!2*sI=c_6_zkDPLIPv(hhZ#%4k3nm)6JL& z4p1sIq9hZ7=p1GesZsd)Qy2K!*Ip)vNa_}d8MP={D>(}%&a8O!p}Tqaqu<2N{tmCd z^)k}J1D<)t`21&|p(_wmaRH!uRJMw+%!!To zjT`5~$pnZES8i+qw3g46CjgF_$6TqD={`0 zNjxu~S)0_m+ zn(mi}O@FCbb=zY(3_$wifAyG*+NHhRKD=6__fG{DK{(vH5FrVKlvvL($43Sy@zwHj z70wXJai;FvFUD$?_6`A#2G~@gnBH`x>g+G6I-dkqz3jtWI97)V$(2|q>gCGRR_@t+ zf%oR$rOsxz=;Q>;8P$zqV`T8>#NG3G%G8JafP&A^!S%qfqgvVgCfT%G= zkBpAyJFJKjED|KT2O@aY`6NP(4o;3JNd--TKx8Sx=rR_kB-PkTbQ`M%w%Z_%9m2+`OH&}9##ENygzepFT#Sc?O>4&Ki41`C)MZ1LS64Segv z%9R%N6}Cd zb|+&H<(4*`yZ>$b-}A)N+b`9v9?dR!KLFyhz+|D|SHc$fn|tHPv)j$ZPpow<-DD5Wan z)+M=9TWF^vKBT|MG8{nloU|c3SeP5=7O>ob*i_>BgYQ07}G8uW9zOhO3+ngG!P2RK;Ss4)`6=d9E6JMbn|d3rhe0#(9A#E5RBwO?tajl_)#3(-IgRWn$ega zCXGQ8A}Y#(xrH-foIbPUz6Z|p;3Mbh#rWbMe~nAezU-D;amn^LIUQGn5bN>ST<3|? zjZTW8;_+Qlg$M2m{LN2vWSMBvY&sJ!>5y6E6$|Vhy~S-iU*~drA6Aq>BHAW$6-rd^ zvfK|$M*-Q5#Hf^Qpvgj+8Kjt@t;VJ*aUtxeuPO(rauVn)x>Q+>1@Gh3)!hBk(Ac$4{qK)Wzxq?}H-LEG$9_uc zGVb1gcJHV5_VdGI1DmaJG`d4?tinbFEx|#%?0S)=fm7KZ!i{-PdjW1#VM4iTFj-+e z`j;{t2QO@AZT{q0fFTqwP`IHU%iLGAAN}MO?_hh+`nUK{|4#{HrL9o9`PL6!F}*tL zp}P45q@YAqB)j!5Rv~71``xhUgco0k6auGm0lSCI2dGDCx~-4K@xxX4X68brqP?= zzJn<`hEheyBDB%hz-&Sn0v&J|Ttp-SQ3aipI4Rq?V_>Whs?jWrJr(jKq=n-qod#l; z_P0SVUB5nkX;_c_^S}FZ3XpWw(X852x9sHydpr~G!2B0JmTxbmf(fR|x+ZkTe}T6K zM=ewIuDa9+8>{X&sc@ji!Nyqw)KBFx&gg$JCYw>iBd`3f)5xfWDJnKi=-N2lzs7eC zzd))JbrPl~kmHQLFWhn1B;T1*J5$eQ&?~m1-Y+otuKMx6>a8oE{jG#;p-6xjiJ`Dt zTUJY_={Bh&wEKjxi^>Q?k2Wjr`lg4u^{%IQ=K0r%7Qg~U)IB%BS(89uGNYA>DKr|{ ziV>>o07@|=C|jG;d8AS?4;97tWeKpzi8dxC37iZ*CN@NR42=Pcfv83^8(QiZX`>ON zkPGwyE@q*W$}}gULMj(-_qE^^g@GMR%-1ClG z`1oJ@X4*zbV^6SMbPyJ+C3|OY;rf;9EQ()R2j($#ZGbJ%W+4rMP=ziy-CSpp&>}{D z=z9a-`o2Kf4AfC63neZg9{8mo+qvp%axnZpeS+O|$hzzhOF*_lUBNIJaVV$-Hs=yi zp{?FO(e8t^e)&~}!zE-h+QAPzP2Mwj5Incwl!cq?@_POpw;`}Umpolbk(ev{ld(}> zw^JXGXkKg98e&REq7`>T-m`2z{)Xv4sl8pjxdO=H7*;#o`5^K3VRDc{tEZ%FQ)Git z$3W7GslZ(N+1EK;YNl+o2L>Z1S2G>p=Cm{eh&4D59t%icX082<7N&}1KQ*K;*m`0b zD={nYzw*nR>7Pc(Nb6Eh2L_F<7;Wp40uI$Fc9L zF0t_Gpf^W(2KAdrQJN5_vs5)H^ax#QI2jWXB4$EK2@R1GxOikG$`p+WA&^-FV->&} zp_Iaj5V?_HHAHT;B}$>UirYqnE*V`DS&|r4h_m6R2}0L2Oc_E9G;Ku2iByD3xuI)d zF~L!BJQ=nADpts_lj9DWw&fz;L1giPraGc)cVk;qN zAz|G0z7T2Sslcq<5f1O4cL+G6%M z)u4RneVI>xUjiK{2NPT`*kpuRG#O_B(W1_(=m;mmE4;0Lg0FSAIdjohYFn_QL{5ou z$LZrR1SI*IQ6@KpwQh*?I2EaEvk*dJIVTepf$b1DNN_rR<2fqgxdQ#27mI!-`?twEW79U$%dFi|Vo5#xU{Pg=ZNlfi7%>y-tJ;hiC z2jUJFf=DH9j8GDrk|-v$>-i;Yz2Kluu$Y@rLWM;KQwMAuu(9Ajv_+7w~5+&Y!f=zv_SXk*;YS9uS=fwh4&3Uq#=ibNKT&{(C-N;u-+oITvMKx=`N z1C1y}0@7rHKx@XHHH=l5;z(13!w~5#GEu2y8a1X6*`>HwLHwqTIUrG3g~XCXQK4-r zO%le1uv0Q2WYV5sldzmT5JD|7N~OrePB2uB12ra9PY$0CzT?2yG~1)|{8db|mLkrM zQJKRVT|sTss$?@Xx#s{0Y;o-4?RVV4ncdr1MI|%|Xgu(6 zFm}2X&5m&6!X-NM@pf%SE3j3gm~;6-l@MJsFjkkQ71XobG-APnAEw~@axx?3z;13? zE{q{XT8XqNvKxe)GEq8~$&D^&V`R|=asx3%O0A?2X+k6iXo4`sKy4$jOLUEYFl|bl z>Xx)!MsiDuk<|>Li7VsamfQLJPxI$; zoXvQ%-$iE%mf0d8ktl&AUJ-ro{bzaq2k%2vIk>u|6eF2(YJbV6KJ`~Pb?YsJP@x?e z%a$7#F7xu&F7WtQUSd&4WS%~%_zI9>;3|gAc3%lXh(aRp=);Mh{M#*O&nnZkp7Lrz zDL$zVGd(>|xI+OQg(L~lK&;A6*zkDwA*OCg%zS=@RTM(*DJ(<74AAynf%e|74AKfBTQuyZ83K@76{Bwo#Q~Q0gSm`>sB!E8*(Q zho;^rGJD&DFye-YoS-foAY_^iVfZu=XG>_*O6vWZs9X15hpBi-$5^O`N{EU!@aXzC z_~7=R(KWN=voo~w{i$hOh_!oK*x50f2GYX3Lv7ByI8MLyg3+5-j;9Z2rvT5~QrX`% zuD+6yq0%OA{kbtg%#qvQekU8gy@v&1eRk;jQiT;pJ>#1uJy z&u#3TTyb!H!=x_e5h~GK2oo{3rWEuhzid`HksF#6W`Txh#z{yt5@}#M;V7C=^Q+7>$$Ru^K z&MHBwkt{-Aj72T97Fkb~wHp06@WysSKh>M@>)u1^`H9ClRCXLAKTDgNSt(iP1FH$} z=)2DG1D}2u?|A55?tjM}JoVLA8P+}bts3q+x5FbJ`4;w0wpbh)b<6cDhdlciFY`yA zdy=x=aCY_^#kqxNJ4Y8<2uwPs_5zIx_dgu?ksnRma*Hwzg>q0R+X;Pbm zuWSa8FP8fE!$EvS0P4dHSDc;0YRS;47V3g`B`DTDn9Ypd5tjZ9DrW%@+HXCghmRqyy z*Dm#s_mpjX;WPh;kA3p*e(&inzE6r$EHD)xnTIIU8cCyKO`s%08h5v80Y=Zx%XLnT z_P}1+X?EyM(5QOTR&fK(G#P0En+iHA*3UrFXapvvCUCku!zW(*8CK~!mIE<+3eTnu zEC{5cG-qJBJI9VKf{&TQY_^!KzBh&7d43A#ST0YE3Ir8S-BCGnOXb?tj)OxXQcwx3 z*CRXKg0qVyy6gxd#BoAHPbPEw`CD0??RfdQH&~TQ5ICyFhd%Ode&X-^5a0IkcT@9{ zuRn7En+hC71D@8l616_nJ1sXC_guUDlREWuUU6aUOQbG*0 zIS^B1Nkh%Tt{5pKRvGp?SV_y7yhM@%f2$_2Bax5<(LjR(Wz^tFyy~=Rt%WOPWGKp1 zCa#sj;kf0^ZO@HbTwOe$yVLBmx8o%8<6zdAjgaU(cnZ8pg5m+S4!a)EA!M%H?b9c7Y(XJUIAtx(Tpb z{qWz+fyk2z?|oO`hkqh-%UNYy7s|R)uZ`$f9mlFZYU^d#6l09SxN+s4PKiXI#DIpv zA{L%nevlfL$SRqZOBgKqZXZKN2goFk~L@85X*jB<0#28Rh+A$C(LDi^rPSMTk_1&X$zbPARj2tSZ zg@KBUN|F&>7+tx+2Zw*msl}TFYp78PCAsKlm}s-m?hDHurQNSI+0jzThD5NzEs`we zPj+xTf*lV7unA&`ggBv%R~p@Vf8~QGZt$glwdCUC4QDdER4PwB{v3O&hVv&{CKha| zgfX(Th-qZ++#a{xe})&Hc!k}N2>UyH^sjw@#i@vuCEx#}KSJNb@BYefqZTl6I;+fd zSC|`?q8;0og=zs2HzG~dW3(oWJ_HsTxjw;i6l#XU6o~|O16~eNgp)CoQeYzkO~?#& zq)K47bc~I%4oVn}Y?Z!7a!9BJdX!iN+Dab0e(i`tjfv7vFpOL?<*?s!xZQHSALiA@ zAK^lEag>Q`A-rUbJcq%CI2XsZ4d420kMQ6lcQPHVks{oC=ULKDLD^x|tq5h}&b!X? z))Oz$}z*LF#8*a-`T~p9DLSG`J$hh_hI8{%MT3Y69`V6;@7kIrr zg^nY63WSS^x~#AWEVNRGK*$MA%4VON;ICBA2_Vf>C3EE+HotemQG`DE?=TeDosR3g zT)Ws>pcZAo*v@j}IN+fDOcySDp@=dqg|$ZNP*|pPZ+p_t$|Nr(fPS#Ih@SIX4=RO9 zBCr#Mqp=bKw3A>IMiYi=gg7BfoW58WX9pJMa!+-VC1$1i=Sx!q(8 z7I)<3$lV8jSns?3gxG!#940bK+O6zvj71fi#%P+ts;zV)gz9>7X3ag5AuFFcZk7Nt zm*R>+D%94{DS4e%QqmYXaa-g&{`wJLJKgchV=bug{J7UQ#fNvmI-dp@B%1(hv(45JQ5+^}6e(Hw+HM>>V7Bi5n?gLnLfl}d+ zLT-Hpo2n~q*8(ThSW#W5XGWimaq9_OW$xE(@$ir#374(XVeBBRbfOE;nVddXQPy><>@Za`5z}3-Qk8A-!<2YfVU%(s)3lwv~`7 zc~8m9hO|&bCL|czxB^hJ@8ZY?Ze(!tv4}bbU;T`wg$$04rw%0FGV_{tPy!gT+{M`^eeNm713t!D%8|5W0kcY7kzxK+xw zF!dF!l~R>B3)4I-RL~lz;w6^h5Yp23^)k$QmH?Xl6#u6BhdeHy=5V|Rwnkn?M2x9` zts?Cx#Oz;kGs}~;HEe)pIX4Jr&nU>XVo8ue=zwvmXz?dj5yS#F#3|M(DO#Kl4%`K=*cd|7S}XVX^iK6B;FXpq(s&U!U-TSk((hCrkcPDSEqFnACLX-+QL zm@6nw%`bnPqr#6T17>7uBS=>X!N4+t@b-64EKez4`lTg@Z$&~fUb`}K>C3OsRps8j z6V#&~v4JRsR$#Y{EOr|#^nR^Rku)jo?vnez`J4IDV~^3`(OlKOaTw*`E5K&Hp=}(w zUX3Ppj6rE7A~i8sCC7Q}&%z=^7S*}ziqlO)EochpFtVOK7Tck)9k<-rj$G58IvJx@ zm+Q`!*doS+(pC>1Nyk#zkV!VUkjD}tff6b^dwcxY-}{ewQ57RY$}feKAu|PT6a`>);P~?Bsdc zZ6VbbTULSuVqYOePgzq}>(yC>zl^SmW%Am_&9O4)$jEd5VK-0DQXONG8lg4DTG{$A zi%!t@bBdd1ks`TzYFBifKvQOOSqtk%Ss8S@;SRYNcYFnCx38H^&l9^lq$6G?BI&2*EAIRHxWdF=P_2 z6zv4_UWDQQS=JHgSmXE#T5JVKj*+qwJEd-%ow(zrK)Z6aX+_vrqA8ANiAIQ(hmQV$udP1GC}-R% z-cHn#C<}8AUL#HCfSxuLje=D-C2923X^O`uHU;khoWE14g<)mH0aVJ2uzFv>LR?uJ zC&*j3NFUX}UU5IcQsJl++F;~GWf~)vU@H-ku*X621K@BfM{kbPSKfBE`*1#rY=Sab zzy_#GFY6eBlIGOXiY?eYte;YF)Fk3cM>HX&Ofd5b z>ElAyIjtt{F8J_AznRmgmVEB_zQP+94_M|*H|zO>h^N_V#HdV@a#%;ks-9C&g;Jr5 z!H1%du$hXK*^4ll$7YY!YuN`88Ui2ttMB7S|LzacP+4EQ&j0%CucEbhNTn%vy!|Y@ zyGw3j|6wi*l|agwcCk;new{iPl6ScO(RZ-;oj>8=jVlbBiN#(+ z|6%XVgLTcW`n+fDz2D&*&Unuq&+TsYK(_`E5`zR1U<3$kVZZ`A7$?RUa3y#kt|SJ> zNs7X*N~nNKDU2QB7@Oc!?6~ZJ6Uw+O5HbWIB#_X6)RKC-^F8zV#&_7m${+i^w@o2q z%0-H@;H~QFuIjp{PoMMc{qDWiZ#_>%QgG5?r00AQxHP@aBRjja64B`Ki=MR;LX1dE zV1zDuMq9!&pC`QjjRhC4DN%a5wZc508t^`%K9XXdPsy+L%-WNfTNYY56oHMQ{k+OY z{i;%ySn3`+XEXD(6hbiUn-_Vq{RKWb`s27dJ0!&iOlfgZm{_3;iZzzx^Sr;bN?Rw& z2(r!rBV(W)lBH(#z-+D9HbZ%n&3u69GaRPVoVE=nLqzH%h{>7H6e4p6#wo4j84QEO4#xz?dicw?>Xz^b15#)wqtWPlG#ksYH30{ z!-Uzcb62WMFOx{Oj$$=4SK-1s0M#HQSeVeo9Ic|ekU(4$Id z$Z!W^6w&M#8*RbXe&pbmW4SWam1BQro68rs7#W+D_r-|DcZ9k?HUsK&p1vMu;21Hm zb-7}HFR?oBIGgn(ClB@N)r07QRbN^U-0J7Wph&Ti@)#@PS$~i zZ&`L7v#w>?_MG&Ib?0egU>O5e9Z?O_iRDdie1=I~a`${TBni{dqBA5_wsxjG`B_)E zc}UDHu&ameJlU*cYZA!({1{drz{G7<-H$awd`<`QQ)8ZhS%~XU;UQBc-ccZ z8!SL0L@TUh@Li{nnuwUl```BoRD>`5(pNLys7WE9X$;8|f~RfPbgMP4eZFmR*h?h5{aaP2$Vm4zK(2#AGAn8H?cYhb?K|le$1^ zrjkCNMS^KKdqMQZ8f^DN?)Ks!5}QowV-nym0rI z4o~d|i{KU$6P9ZGE|r=pUpQxEyqx!EC(`NTkM4cNsM^?cQc;#I5_5o(Dsxei3X&qp zf}M~{qKyo_5y{`%BBG_D16Ou4|1|Fd5th8~j1 zEkPMV8v`ZhZEyd>{GqqK6^S!Q@Of{3HT#cWXY5|M zjD{i~)H+z6pU|z9zB!>k_pnN|T~B4kJpF}VOn2is`j81!nhF+OL*J|zS=f3^dFqXx z$3I)CHk9Ba-8v#6qVtx}2GoJHVEY_aBfV^l)hL*;!8VD|TGYreHZv%)D@&U-&i`Cqg!FF_stQ1HH|ytIw4mvjdUWKWUZe5?%fp3=4y z&59yL)YV*nbeD@e8{9uU%T^-wL^14cZIgV&RTXdjy01svW-bxauzleQPrULGKKaob znT}^1ZHkOhgq~7z8!=%hNPOcre-+>S9e)g07d-yV6I{D~iH|?~61A})hPqI`={x@{ zpa11=fyIju7Q+!<2YE*xGZtqkD$DC%`zRm!)#s29Gv&GO(E;%CP#PlDP|+#|wqBR# zB2-zP_gswm?Q?W=pU0kh3>8Dvj<)SsouAU2xA@@E)DyMi^!@?6o0qAy=j{9lZ}ZW% z4?WUECS%9bpV#u_n*!4diZ+oj^Q0~i*PhTuqzjn%vXoeD{=H!HF^c}Byj z5RiI^kroEqILc@lkCoV4q8KoSjf{gqfLYq;($V30xp}xF8NO4d9(W^!fhkU;p_3_4roxElFh3mrAi^F`ZKQ zNE0nxA?(InF+C#}2i+*20;ee-$8C&w7b%vx4p2`awTWpRD2l|$Css&&;r7|TzJGN8 zUq<}B!o*`nIx}Iqmg!xel4y)tbmuZMW4k#?a(;eiu`0(BN3Xp4wG@*HY1kH1gGpWX zb4esM7O{#A1#Aow!jSJmDcX!JegG&K{D2SeWDG1rO*uNLlJUmU2DG$nT=u-?kDhS! z>z4Cpui$4LU0e|ECpJysrTLnR^EKPk0-Xlh)KjJ&BZ}MfNUE3=d+c4=<@Ui0Hz38o z>`hPewr_kZlgSpdweX53A0MK0*<@h~&#Pbc1n-ph4D?kU5ZQyJ7tPiol*nnffWdoI8767A^?G%AuJGHZ#pckL}Fg# zSpqk-oc2L$z<+6cm)d^JzA*R()4EMaG-)siD zbF_Nzz2)S6m$%Een5fKRmUmiULp_t;kZi$nn35V?4@^{si^)nn~aEGF~PZm*P`zy1uKnN8LPFSrwJ- z{QdKvJFASj^wi$l%xG(@Z8zk6mk)Bs888_Ko{|npwMt3z2b4*dQxn9DohgPBKskJ= zhw_|65XBT=$3x1nx45zA$`{?I-YEFgFK;kA>?vkz>UzvZ3D3WHo7aq>@Pgm&A=Ma( zl%}L>9j2_fvbDja5K>IM=C#l8E&s_^bMeuq*uJ<=G2P9i$fOzLEe(j}$|IN1+Ceaw zfq&nkOr53FjMx$p-uj2Xf@{}bmB|x2!#d03pY<5Xd$5`_{#%!>vb}R5uL|P^GfO?J zmf>t{R)`pI9d+p_oiK3~+qR%PJz+JQvAuU`Fu^>q0n5WbA45aXB~9o#KRjfwHtcLw z%b{Y&ya+68p>&Q+Zj5NX&O?lR#@hLN26+ks(ASHG-6oyhXf23VGO9GtN;I z1#we|S~9{C3kRJLouMC>tCRc1OKlp>ZCOh^y0wh;VP&pd-`y;fWR$`uib6PFBxI6v z6rmIR*uWT?E_Y_6wiG6if>L-(Foq>cQ7I{8HbYr}TS6g$ZqPyaGIu7N#tghoCi4#` z!bYXw^Zbk}@(IAt{XuiG{8;E#>)*5i%w2!}v7610Z%&IZUO4Jf6sa?}ejK24iMG&O z3~Hee&9nR|5l4cCl6Bu7H4MEe`J4u1UB3kUyjlIHg}+}U|)jvCju z-h^cwn-yl|aAjm_qZwOcr8g_aah;M`cb!?Ey>#5VDunGUqxB4V|{^e%6vFzpP=po0BiHJ2RY+ihQy&!(TN=^jL!)U9_M|8ms5ZZ)B zp&+8h&@W?Fu$2)SgOkLDW=&W>Oq&*}jO+Y0(L5zvC1t~Ah2Kf&KO(xm@t*H{bNWpi z09D7WJLmu6(M#1&UcXR(i*>mWSXnaU0PtPz|Bc2_uVQAGmBNCAR{8B8eZq|tHx5)@ zm;}WVSI^x%`jPuLZvVLJm&dhTuXTOu!@AWU`-yjiPh%~L|KMA{Aem^QraEZZ_<##l zihlWtv;SMXi91hU`vx(SDMbZlnaiJUm_yYEQ*t)L_si^dCk@{4Zh-CEyg5iaR90Os z3aSh*(Na-7+FJ@0#1C)D3ie+)qbL&3{)XIhigVhuz&qBW#bS$?a2|dgE{SbjoXB$zF@`GH>`10e(P(Kh)qvSo-_-@ zCZIO|sN&Gqk82(l{|vbrFP%Vb2@iN_np?3tT%|~s)Ejgon|li_a@%XC#P%*9%63X> zQ_&oxvpX;KzkKehn_cO8FGfXM6Z*@wFOO#-+^?(ABd<#~N+>-_!Ppom6AKc~33V+r zE5&$NP4YbNLo9P3^lZ8 z3l^t$SRb8p{K6TRs!evxHad!^E8y;m^OKvzt%|Lppx)Y~T1C`$G-oa6i#a~5ne2Bw z{?;`Y9&MntXq!pBz6r$R9(*7T4VuD zkrEEgDmxqV4R&OxQetY9+Ch{^l`I#5!UYy>ynAOcf7hqA13!5F<$wQ0&rW~f{oix> z=_@}`I(JQrjK6A2K`_)Poym+eTW71whE;5ru#-p%|{-*w$jPl>^`IA5VsrWO0{_%AaVi&wyYG)Sig`@MB+WGdY_P@=P z#U7!Ab(!OV-VEBj;XK$%ep_w3fzPZtedP^C3Ze^0%-0gFjg`I~G#d4YLcvbw!sr;bc6Iwspfv$(~0 zx|fSs?g%Msgc_5UL*FN}14kuX+1kLxz*HR8D6f3_8dn~FJeP!153GnOp{d6?dFTTy zii%=1q1F|3sYqD zyA+#~yixU2a7%pGGe0|_J!v>PJj0)@cy#ju#fBrS8YBwkhGUe#N^T`eY)EY&*g!~u z+66AZvg46AEGTya8Wci6LnNH`L_B^-d`g740cjpFeRh98%zFTgbHrC&Chr()Nh3$G z0$lMv=HOg zB|aqWjhbdu#_^_Kg!S>QTmO1@b93aVu2xAglL9A^ItiUs!dxjY8+0?1qq`c)_23|I zIjw41NM*wLJT;~^61-5C2~Em$0qrPX;UvPuCA3d;F<_i9GQxHR#VBG6%ct%ye)+WR zU;1q~0Dyn`SHJM*CO`1e|K@eC*?q?dwnrn+c3+Unh%XZ^7#0PzF)|JjJ61+pIj`JA zsH1fEZ~J$D^b-d^dUDeKa$R@x;FjIH|K4{b{ym>R@^@ZTAiVo8J+h2#8CJdY&GXBD z8kYyFo!9MuyDN7ek*d#CeVc0%8P98S&!-5OE@XK~wq2k>b1b%YXrItHr1T!l4Lpzn z4fjd4Y z&SAA=78-1;Y#@xrBa9u+cp5OR z91so@&Cwx~YCjtULUFm_`sbXmy}!h0L_3ok6m5_CKv?wz5?Z;34hYketIuU_Nt$3tWj_8tFeynb zL^1hy8wGVH*$kpYqbP-qQkob$^=w#AXT9yUiAL9*wd-!3meTd}cB(UT-p(A_m*ryJ z8WwwXTAeTHHUy1?!d3mOj~6yq$NlQ|M~%Mfm9PH#aar!IQO0U$ok6{Fp-{p)u@dl3 zsH0#*q8;TTr7d!Ei@8FP&y2(JcyHUrfBqxir2H;DU;ejlrC<2ZAMa%BW+sSRt!D3ZHBr= z?trd2fwPl5C7vA3 z;()$Ws(PDhEWnhagx!l%`kN(twPj-0X#Zf$O^Gqkty{cr8BHZ8W^jaVMQnSz)e5r~ zcDA=E(k8AyB+QPOpC7P$WsK3>pzc;n4sV}vdTYhqmyRjV=Ul%23RDuQmt3IhBH9Rj z2$*TWVNkQCT_mPYpL6Mr$JD#)T!2NK5gqmoQR!*Z6j2|Fhr3<meHAo4{~ld%vtJ- zQ(dNoN$Yd9@uUd-+1lH+Xwh0UT0Jv;h=s~{Jns9Q`QoM1TQ}-v|H;Sy_{C9q*~dg* zD$~x;H<8Z3r~n%irY~r!gsFsjZ5S7l5$t2dSYhe&82QA)vQpmVGoHQT2d1v`E$M=^%m-_z3WHNFYgedquwfr zg&@mw%8i1_?jC-Xm@RK}_xvVT+#cQ0g5G;Z@szlAIXA0|m?uPh4%AG?6;&zd)KEpC zJ6_P9oip9pLQ|ycX0*!_`nW;coKcR-j3T3FXUDP_TSm5qbs%*iTP8KPO?}_e1w+|| zp^nh8o}KaHvv;|F`N%5DS3}352D0&xZn>; zZRv(f0Pd3x0tMT&%YizG?b8l`Y*8l#jZ#gRq|>x~z$*glS28$)W;*rgUS zw_Ss5n|K#`mKsmb0>2pUb2x%M@Bwja_A$qHv~M*4AA*OTIk6 zb?@Z#yeLkdzIOea#+%bumn4Y=6h5%&601;9uQP{1s+g7Hl~4vl(Hn$-Z3T6X!a%Kw zuvGeuh^r$th9V{A0~M)KVJgZv(|?F{qG|Q^$6lJh;}_rYhV$R52mg0GKmCJm{=n&< z|JlFv*unC#3s<&Ydy({txSOt?8pW;T;Am-XJom!cvnPIbC;0iYZpLXVZRk6H@GJG5 z{O&(*`QaD!|NZYC_ulE!^hPz<6s)L9j8dD<6sgsg*3_=Ygl$y`tkYPgHX&6>>=Qy^ zHjGstjG73lQ9G9h*L}*~fGVTI2$3i+gBxPXZS!c9)aoE28LH{gVNzo6^(ScQx%Uf~ z2&uyK1>#&z(=8I?X~FK9;l?KpnIE+5j%!jZ2wsWN5|hD%9FFgAa+w+Deo_K=M)-I2&W%>p8L<;r8kjo8HwjBCLyuC zyUq1$*C@wATm+fC9pZ9k%u{c%3<*v&{l?wlOSUu_7)jQve;yj5LMJT8;wd-V|BcalO~DQg#?NHpH$lV?gqBaD28&KiN# zC!)fn6kHI@Dr=@|QKZi^0~#ZJX{b#O0cor4FFbqpKP;Br`#!B6{CD!a=kI(~d=I=p z{_FSr`I5i!q5}SxzURqhy{|DeCd3uJvFhzay(_iHx}aKkA49NWgKJ~d+Kj}wijh%L zDiAEu8bUP0kijTUbc>ed z{0_~sr)?KRUvPMM$h}Y8;q>D-*z=YrKI?NB?N0IcoB)EfqYrey&BrqW@!P)bdwk`z zJxk>(^!+S(ck;r=y4$n)@}o~bb@fkO+AN-0#YArt#t0GlW9*52Ta=xx(t6%? zFWx_HKN3}$jH>O9~fCS#p4@>LjJ^o%dH%1wL?@}ESgN-6#AT+j>#fb-ei*}iM2|yBCQh5@5W=onhp-dxEs<5WShJrp6 z2DMrwV>C%pZ;W_Dp~xE4YPR;oL@bn0M@&2DtWDlgV=LJVTeu-sY@tlFMF#Sh7Jf*dtWyfJ_WtE!HQECaqibr^|D5r?P&UYrpfGF5X34;dBhRizDBI06(F+MyO8o{YW#zT-`nu}B^l$<`h%fWkh z2s)vz3(9f>w^@;#V>O$xo_WGfiMN6-BfD1~r;s_in9(1c;9HL=6+5y_>zcFYUtoQDfcGA>B-(%mOC=>68xzWrB6XR00OB$v zr7UqebVFRCT_yZ_0l|}8mqnCag(V}djIn3|QCi&2l8diCV&ig)8AN-k*#s5+aECt# zXbO1&KbXiI#tTd@5QNm*JVGov^;e`Uo$(3MRB(MULuP2cq|aPDuW=nq|? z%M{eV=kI>y@92B~jNAYKKJb0lq)N^ewH+DDmQ2${r}nDxy6?uiFWc2qCg~+-befz_ zEII-mp<0NG1vL)iEnX{0!4h*K&A8mY(o!+QFk%Wy5fx$}j?=($11$tG7Mmo`aE>3` z7lhT_F~{$}NOQb{U??kx)>CXL&^Ww$Osk}NMNw|CY?m}AZT1BO#Z^60S?b_$ks{Ve~+KB8^FW+*MIet#L$TrzH*gLorXO(;<0LX=WC`< zUH%50xN8zx(SVrPNlKjv9`#XB6=#BI48+t!NO`2x1xy{G&q!a>CQ=J_q{t|ui_B~C zDIpH*NKguF7-Cyxj^X>2V|_AV{?Z=(*%)&Qv8r*w5vQKoLMnQiKH0NisrE1JWXErK|-RbwnF+qeOwhRN2^TH$zsmk#OS#wIVV1JH;g= zNALU z=AoUamLy=>K`yw;bpYMXLutucOmevpyOxaE?Hu4pmBZ8qp@2e3Qemo+!j#0(7*d6w zt!_4-I(gUm&C~a%6z}TT9QjzB#9n7!SbIrbY73ugNnih?|Nox^ey^U-_zmDU1)Kij zC0mWcgk{>Prd*rsPu@^Hb?KYx?cFa-*3|f=ih4*rsy-v4WB>A5GlZ;O8b?eBNQxPw z9V2O-Jx|ssDJ6^=C?b*kwsWc&Q$U$eXCG?8u#m(NW{%iZs2OA@b;OqWeyw3pNtKzx zBAOlob!A{8(!AW%&3ELCJ(u({g;>mB=d=%~$b-Af=Kn>~Anr>FUCLi0q&zoa>@b!U z^ClK~`M+uNhM?(z8<2drk3y=l7#2HNHXA`>!jCn3A~jEQYvYh+AnX*w3`XK1&^1Pz zSr4_%rz<1K%I5pNx~%f`4mA!HK_(?G=7~uyD$I0*F-c-quDX+x53Nq_zdPKGpX%mv z7y?J3kh37N2&HR6N5@tQM3dh3j+^?Kye58MZ2$nj{ymq)v|75c-*72ibi4M6(e;a8 zT|IX3>#VIGC9NQ$sZU_mNZ-C}8|^zt5mN}75`_kWY95Ky!7Vq8WXfPB#waO9C=-Tk zuZe|$G?Idqo4&Vxt9SoEv!{=>|D-Y-3yx0f5 zI^8fbP0C+e2b-#iLy#u3=jjp{MVmY%Xs42g{k$S&9=)X>MsHo-K#a>{xFSmGBdU39 zT77!RSBQ%o+|#Yx(vx!`)>*$LP7sr4i_{D!B_~7-dTOwHh7=_;CX<1X!&SHExiNXcgM>_Db@s4c5_IBTG7A_c(= zkX4GjScDub%DC6TbI>qow*o@QU!%=}0bS)qu0=o^$uf#QuW^leD$*p)ck6i~R#{T$ zLSC$~&jw>sB#J@T2|7WHAv&=0mPztftVMEhAG)4ZN)1V5LLh`0yERqb# zWFnIW3u76ExPToQ99$WEZ$$D5rYFx|m;x;Ytpw9mNMR9Yu$9R>Z&~M>i>(B;uv(ul zkB>gq-aPtne-iGP(j1z;IF6c5wUk**X=$`vTTOi`2-e5QL*?mb_VfGh1n_S@zwuWt z7>Qb%GHp7;1yjo-#rD=0O&;0*T63xXY-^>aZoHUNI(NVs3+(WfoXyot4!Z z1SsQBa^Qarc_u-?v+==TY3PU;1v~tdA?f60QSjO2ti^V#)-r6J|hb9@my6O zh?X-jcO$`95!7R;jQusC?rcN zEzTNLN{mYWIocv4-^&7A-WaIB6&s>BVxvueH2Xw*``-Jy)#|ypl>4SBjukmEhFPyH zJCO!UXZkXDdCq&{Sxd>KhTz)Fak@`!CT*>)@-z2;eUUIte( zKp(XSib%0#h%plT0VXli1H})M!!G|j>GBCfN5j{1!=D`nY0Lmek}gxh z9+17U14U;520dWv$pmyg(2_>vooqcU_)W6gYLIIL4@oRe5-GX-eXS*TMFwnpSc46M zmn@->8Ypa5%1QoMsmb z?8E6qZ$&BYV$Dft+*vESgw*;-7#o+~@b_=&@7K@%A8Y`_^U1$@Nth>V$6ASr8+2SK zHtjRxN4LMSd~E-%c2Yc+;@ZVTk`PdvE9a`7)b!9N)CI5+Ne0t(B=rN_S25maXF>^P zov#wA5t$B2Hu3_q)8T$Sa7;`=CKRs&Q52~Lz-3gzK#zrdfY*O)F&{|7;F^O7*dhJoDwZs7I{Z1>s+U>F8kE90=}QWYs0p+G+A{{Gog44?gvOumOD9=ea+3!KTVoG7cN1 zOM7O!c-7>Qy{|5>UHB?xay{X#(>6&|q6RbuV($^xV{FLxa}8h<8nb{>)Dx=w&n7~& z5ximxMS>8U2+j;_Kt;#dy=VsGYbG1zMXe}Q3H1Ym(<&m_a;ueKS|!*42w4xr?;#In zD~Qd@tw@GhdgJm2qz^301*n(I#B-VloHW5wpc3V$-no17Sut;LK=iE4a2pFh96 zarU$Ay_25}3;$g3_P7c`UjuxKiB|%XV-%7-4m-6M#6|%x5|=> zRaL#FymsL$+?C5;CKI>s`s7qYiV}%FVgA4N&aTC>>o~)2Rjsx6Ieq$jG^3HDF~-P} zLB=Rn67oTEk^B~ifFXt$@+)$mi#RsHzalrmAz)&B+J+9;UP~_;Y$!h{nL}>G%x=32TMmk129KY3mL5e5QlSYje#`QW0x*G^$~zrFGi0u zfRRDRv4X0D1Mc7>hE%&da#Z0nQYO#v(wA8z>2E&k%8VAJ%Q6 z96E(W@mUH1N}x=TLxEd{ihv<-XRu{hpWxJiM8K4ZD3i`QyYGHJe0cT!-3QPAVc6_BQd`(57%GrUOoQ9)q@9r#P`-;v?9IL z(V?R=12#`^5}*{I%n+_HC|n&-1!a%h{$n_mG81gF*mtiH@LW8cj1{0&g^7i#X1C1c z7vo1~z^|9n{>j51u6lSP_PiYXwK#LXU*7u?Vj5Qu$s*q!M_tN~;=pPV;J{zj4+)?C zJ*K5B0N_(x6jo0_N1)k3#!>tCfHGoqHvqmSc+N0lBn9d$@Jhg`fSEzw!3qH<2~-&_ z9YAY984MzHLg4kzp6~u+|MSQHxZU3TVEm-~)COEkoNtQJ_$S|c+Mf3<0sQ~+uirT1 zWI3m-Ywqfi2wsuX^k)CLvp+~@_kTa1<}V?w4oM9xqg5-gc?N1M4zVe0p1|wq$eB5O zsGzLyY|&7&C8(~$P1!kYo=l?zpb9uyC=ge+w9n&P*d_pK(WKifuZ9w_?MtbQ#ViA9 zG4#EALFn>A=$6kgFVAhaMb!gfVBlc6vDhtQn?_)O!NSXi~ML_eS)^m!ZqHZ<39i5h-#7pI%FY;dos>Q{fGy@Jo zEfNa7-l10ptOX(o#ukdl+QHPp8-h)OloB)x$Q@dGKm^1&`VhIo=QViK6SI*~p6zD* zaDM#aNArg-{%O7%f2My0YTH~9R0BokHyFV2V z-QDvK+w;5r0GY-_KpB|sJo*ScEJB=&sQV2-Z@|Q$5=SH{y>$1wvkAbWuyu8?q^Q#w zaRpfkP=>RirUc&#x(omk8+l@o+C`0DfRbWlM_J%CthJdLwn?z52b;v{v#t{405GUh zx%Q_w|2e+@{0H;Z?LXU%zNf&27TVT?^6s~24?DJV zInJ-sYyI2l?DXCK5HG0Pj3IMT<+g9)5os#%tS8hY`5+-`Oejj*lX?9%NgG7t!sEt0}+`8_SSpru4`+hQ{dT^f1I!u_3}XYyzgGR3m}Ug67H zEvUl!cHqu`000CfNkl8^`zJ8BLOprWx9aauMWTErCkw^JK`V#lYZ}$(+-XdN-(vy4wla8tZS)EIP z?FaXcm)C*D4ghlm^nOVMyxbnF{IZAO7T^3>&KJkvJxT?mXfkdkltBN(HEC)1aU=!n z3A6_c3|`(w?}0_GKd}S0?8o(Chp-KN8`~F5`;i&f)#g@qC?r*<@Ra$ z_}Pc1!;|^N`~g+{*n~d8j<0Nw8(q^DM1x)1M9c+AYgJKo*w?<-zV%xI_%-6+|MWgl zcJ{tzHguGHErm|Hjvx48enhVxypdLi%U^rWfBymX+3kM6g-hQj9!WA@;s0*kx`k&x zbNu485niJ#pvfV2J%39}`R@%q-0z?4j}Q|KW8o>k-P{p=(C!!OLQRc@hW83iOv$dQ z%sx=e(I0kNG31%h)X?#h~I~)cSiP(`u)U z4=!65F@?xZUR|wa_Rd{?gXya2W;ye3J^eEA)jx4NKmS*`KReof-rRCN{MyaDeMeQA zl9;NW=dX|2u$|??k9gIV{CUDVh0h*ynPV7z-beb@hl%+=Oy-}ODSx6iqFnyPyJGd{ zH8SsHK!(X{vEa-J88CFFW?Oe>}B1MJ44{z@e5M%Q)F5HBQ>WpJzAYRh!l%f0G+N)@Pzh zuBB||kJ<1|$ssT`b;jP0=GS!(NcXxezL;SmMHKZo{AfLMKhHYuq)i7;F#v(5tDnm{ Hr-UW|3sd+5 literal 0 HcmV?d00001 diff --git a/config/ROUNDS/config.ini b/config/ROUNDS/config.ini new file mode 100644 index 0000000..ac936db --- /dev/null +++ b/config/ROUNDS/config.ini @@ -0,0 +1 @@ +seed=https://arch.myddns.me/app/lunch/?rounds \ No newline at end of file diff --git a/config/ROUNDS/icon.png b/config/ROUNDS/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ed1f5feb231d8267cc10fa6777ab21fdaf3e6118 GIT binary patch literal 28227 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 QfB*mh07*qoM6N<$f-U<@@&Et; literal 0 HcmV?d00001 diff --git a/config/Sins of a Solar Empire Rebellion/config.ini b/config/Sins of a Solar Empire Rebellion/config.ini new file mode 100644 index 0000000..2133ff7 --- /dev/null +++ b/config/Sins of a Solar Empire Rebellion/config.ini @@ -0,0 +1 @@ +seed=http://arch.myddns.me/app/lunch/?soase \ No newline at end of file diff --git a/config/Sins of a Solar Empire Rebellion/icon.png b/config/Sins of a Solar Empire Rebellion/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8219f147c1589c1ce1a052493e0b616a55ac0d40 GIT binary patch literal 81881 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

EK`r3q+D$+cfvAd>P%JH`dz)bg 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 C5adGu literal 0 HcmV?d00001 diff --git a/config/hoi4/config.ini b/config/hoi4/config.ini new file mode 100644 index 0000000..eee9b47 --- /dev/null +++ b/config/hoi4/config.ini @@ -0,0 +1 @@ +seed=http://arch.myddns.me/app/lunch/?hoi4 \ No newline at end of file diff --git a/config/hoi4/icon.png b/config/hoi4/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bc867fc809b318ef3631fb24eb90a492fb4dbc1a GIT binary patch literal 5087 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 BzS95z literal 0 HcmV?d00001 diff --git a/config/meson.build b/config/meson.build new file mode 100644 index 0000000..3522d77 --- /dev/null +++ b/config/meson.build @@ -0,0 +1,12 @@ +games = $games + + +foreach game : games + executable( + game, + lunch_src + windows.compile_resources(files(join_paths(game, 'resource.rc'))), + include_directories: includes, + d_import_dirs: [game], + link_with: [lua, luad, toml] + ) +endforeach \ No newline at end of file diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..30b16c0 --- /dev/null +++ b/meson.build @@ -0,0 +1,98 @@ +project('lunch-games', 'd', 'c') + + +windows = import('windows') +python3 = find_program('python3') + + +lunch_src = files( + 'source/lunch/color.d', + 'source/lunch/conf.d', + 'source/lunch/http.d', + 'source/lunch/launch.d', + 'source/lunch/logger.d', + 'source/lunch/main.d', + 'source/lunch/ui.d', + 'source/lunch/update.d', +) + +toml_src = files( + 'source/toml/datetime.d', + 'source/toml/package.d', + 'source/toml/serialize.d', + 'source/toml/toml.d', +) + +luad_src = files( + 'source/luad/c/all.d', + 'source/luad/c/lauxlib.d', + 'source/luad/c/lua.d', + 'source/luad/c/luaconf.d', + 'source/luad/c/lualib.d', + 'source/luad/c/tostring.d', + 'source/luad/conversions/arrays.d', + 'source/luad/conversions/assocarrays.d', + 'source/luad/conversions/classes.d', + 'source/luad/conversions/functions.d', + 'source/luad/conversions/structs.d', + 'source/luad/conversions/variant.d', + 'source/luad/all.d', + 'source/luad/base.d', + 'source/luad/dynamic.d', + 'source/luad/error.d', + 'source/luad/lfunction.d', + 'source/luad/lmodule.d', + 'source/luad/package.d', + 'source/luad/stack.d', + 'source/luad/state.d', + 'source/luad/table.d', + 'source/luad/testing.d', +) + +lua_src = files( + 'source/lua/lapi.c', + 'source/lua/lauxlib.c', + 'source/lua/lbaselib.c', + 'source/lua/lcode.c', + 'source/lua/ldblib.c', + 'source/lua/ldebug.c', + 'source/lua/ldo.c', + 'source/lua/ldump.c', + 'source/lua/lfunc.c', + 'source/lua/lgc.c', + 'source/lua/linit.c', + 'source/lua/liolib.c', + 'source/lua/llex.c', + 'source/lua/lmathlib.c', + 'source/lua/lmem.c', + 'source/lua/loadlib.c', + 'source/lua/lobject.c', + 'source/lua/lopcodes.c', + 'source/lua/loslib.c', + 'source/lua/lparser.c', + 'source/lua/lstate.c', + 'source/lua/lstring.c', + 'source/lua/lstrlib.c', + 'source/lua/ltable.c', + 'source/lua/ltablib.c', + 'source/lua/ltm.c', + 'source/lua/lundump.c', + 'source/lua/lvm.c', + 'source/lua/lzio.c', +) + + +d_source = lunch_src + toml_src + luad_src +c_source = lua_src + +source = d_source + c_source + +includes = include_directories('source') + +toml = static_library('toml', toml_src, include_directories: includes) +luad = static_library('luad', luad_src, include_directories: includes) +lua = static_library('lua', lua_src, include_directories: includes) + + +run_command(python3, files('prebuild.py'), check: true) +subdir('games') diff --git a/prebuild.py b/prebuild.py new file mode 100644 index 0000000..9201e53 --- /dev/null +++ b/prebuild.py @@ -0,0 +1,117 @@ +import os +import shutil +import string +import subprocess +import configparser + +pjoin = os.path.join + + +def read(filename: str) -> str: + with open(filename, "r") as file: + return file.read() + + +# Prepare `lunch` config template +template = string.Template(read("template.toml")) + + +# Prepare games directory +if os.path.exists("games"): + shutil.rmtree("games") +os.mkdir("games") +with open("games/.gitignore", "w") as file: + file.write("*") + +# Read config directory +games = [] +for dirent in os.listdir("config"): + path = pjoin("config", dirent) + + # If not a directory, skip + if not os.path.isdir(path): + continue + + # Append game's name, and print it to the console + print(dirent) + games.append(dirent) + + # Preprocess game config + config_source = ["[main]"] # Default section + for line in read(pjoin(path, "config.ini")).split("\n"): + line = line.strip() + + # If line empty, skip + if len(line) == 0: + continue + + # If key-value missing, set empty + if (line[0] != "[") and ("=" not in line): + line += "=" + + config_source.append(line) + config_source = "\n".join(config_source) + + # Load game config + config = configparser.ConfigParser() + config.read_string(config_source) + + # Prepare flat config + flat_config = {} + for key in config["main"].keys(): + flat_config[key] = config["main"][key] + + # Set defaults + def default(key, value): + if key not in flat_config: + flat_config[key] = value + + default("name", dirent) + default("exec", dirent+".exe") + default("workdir", "") + + # Replace slashes for paths + for key in ["exec", "workdir"]: + flat_config[key] = flat_config[key].replace("\\", "/") + + # Add exclusions + if "exclude" in config: + flat_config["exclusions"] = list(config["exclude"].keys()) + else: + flat_config["exclusions"] = [] + + # Prepare game directory + opath = pjoin("games", dirent) + os.mkdir(opath) + + # Generate `lunch` config + with open(pjoin(opath, "config.toml"), "w") as file: + file.write(template.substitute(dict(flat_config))) + + # Generate icon + icon_png = pjoin(path, "icon.png") + icon = pjoin(opath, "icon.ico") + subprocess.run([ + "magick", + icon_png, + "-resize", "256x256", + "-define", "icon:auto-resize=256,128,96,64,48,32,16", + icon, + ]) + + # Generate resource file + with open(pjoin(opath, "resource.rc"), "w") as file: + file.writelines([ + "ICON\tICON\t\"icon.ico\"" + ]) + + +# Prepare meson configuration +mesontemplate = string.Template(read("config/meson.build")) +meson = { + "games": games +} + +# Generate meson.build +with open("games/meson.build", "w") as file: + file.write(mesontemplate.substitute(meson)) \ No newline at end of file diff --git a/source/lua/lapi.c b/source/lua/lapi.c new file mode 100644 index 0000000..5d5145d --- /dev/null +++ b/source/lua/lapi.c @@ -0,0 +1,1087 @@ +/* +** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lapi_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + +static TValue *index2adr (lua_State *L, int idx) { + if (idx > 0) { + TValue *o = L->base + (idx - 1); + api_check(L, idx <= L->ci->top - L->base); + if (o >= L->top) return cast(TValue *, luaO_nilobject); + else return o; + } + else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx != 0 && -idx <= L->top - L->base); + return L->top + idx; + } + else switch (idx) { /* pseudo-indices */ + case LUA_REGISTRYINDEX: return registry(L); + case LUA_ENVIRONINDEX: { + Closure *func = curr_func(L); + sethvalue(L, &L->env, func->c.env); + return &L->env; + } + case LUA_GLOBALSINDEX: return gt(L); + default: { + Closure *func = curr_func(L); + idx = LUA_GLOBALSINDEX - idx; + return (idx <= func->c.nupvalues) + ? &func->c.upvalue[idx-1] + : cast(TValue *, luaO_nilobject); + } + } +} + + +static Table *getcurrenv (lua_State *L) { + if (L->ci == L->base_ci) /* no enclosing function? */ + return hvalue(gt(L)); /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} + + +void luaA_pushobject (lua_State *L, const TValue *o) { + setobj2s(L, L->top, o); + api_incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res = 1; + lua_lock(L); + if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) + res = 0; /* stack overflow */ + else if (size > 0) { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to)); + api_check(from, to->ci->top - to->top >= n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +LUA_API void lua_setlevel (lua_State *from, lua_State *to) { + to->nCcalls = from->nCcalls; +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L, L->top, L1); + api_incr_top(L); + lua_unlock(L); + luai_userstatethread(L, L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - L->base); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - L->base); + while (L->top < L->base + idx) + setnilvalue(L->top++); + L->top = L->base + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - L->base)); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + while (++p < L->top) setobjs2s(L, p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + StkId o; + lua_lock(L); + /* explicit test for incompatible code */ + if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) + luaG_runerror(L, "no calling environment"); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + if (idx == LUA_ENVIRONINDEX) { + Closure *func = curr_func(L); + api_check(L, ttistable(L->top - 1)); + func->c.env = hvalue(L->top - 1); + luaC_barrier(L, func, L->top - 1); + } + else { + setobj(L, o, L->top - 1); + if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), L->top - 1); + } + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2adr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2adr(L, index1); + StkId o2 = index2adr(L, index2); + return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + return res; + } + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2adr(L, idx); + if (!ttisstring(o)) { + lua_lock(L); /* `luaV_tostring' may create a new string */ + if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaC_checkGC(L); + o = index2adr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) *len = tsvalue(o)->len; + return svalue(o); +} + + +LUA_API size_t lua_objlen (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); + lua_unlock(L); + return l; + } + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TFUNCTION: return clvalue(o); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setnvalue(L->top, cast_num(n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n, getcurrenv(L)); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top+n); + setclvalue(L, L->top, cl); + lua_assert(iswhite(obj2gco(cl))); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_gettable(L, t, &key, L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L, L->top, luaH_new(L, narray, nrec)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = index2adr(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttype(obj)]; + break; + } + if (mt == NULL) + res = 0; + else { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + switch (ttype(o)) { + case LUA_TFUNCTION: + sethvalue(L, L->top, clvalue(o)->c.env); + break; + case LUA_TUSERDATA: + sethvalue(L, L->top, uvalue(o)->env); + break; + case LUA_TTHREAD: + setobj2s(L, L->top, gt(thvalue(o))); + break; + default: + setnilvalue(L->top); + break; + } + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + api_checknelems(L, 1); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_settable(L, t, &key, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + luaC_barriert(L, hvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2adr(L, objindex); + api_checkvalidindex(L, obj); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1)); + mt = hvalue(L->top - 1); + } + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) + luaC_objbarriert(L, hvalue(obj), mt); + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) + luaC_objbarrier(L, rawuvalue(obj), mt); + break; + } + default: { + G(L)->mt[ttype(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + api_check(L, ttistable(L->top - 1)); + switch (ttype(o)) { + case LUA_TFUNCTION: + clvalue(o)->c.env = hvalue(L->top - 1); + break; + case LUA_TUSERDATA: + uvalue(o)->env = hvalue(L->top - 1); + break; + case LUA_TTHREAD: + sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); + break; + default: + res = 0; + break; + } + if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + L->top--; + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define adjustresults(L,nres) \ + { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) + + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2adr(L, errfunc); + api_checkvalidindex(L, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + c.nresults = nresults; + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0, getcurrenv(L)); + cl->c.f = c->func; + setclvalue(L, L->top, cl); /* push function */ + api_incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + api_incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->GCthreshold = MAX_LUMEM; + break; + } + case LUA_GCRESTART: { + g->GCthreshold = g->totalbytes; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(g->totalbytes >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(g->totalbytes & 0x3ff); + break; + } + case LUA_GCSTEP: { + lu_mem a = (cast(lu_mem, data) << 10); + if (a <= g->totalbytes) + g->GCthreshold = g->totalbytes - a; + else + g->GCthreshold = 0; + while (g->GCthreshold <= g->totalbytes) { + luaC_step(L); + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } + } + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaC_checkGC(L); + luaV_concat(L, n, cast_int(L->top - L->base) - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size, getcurrenv(L)); + setuvalue(L, L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val) { + Closure *f; + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (!(1 <= n && n <= f->c.nupvalues)) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + lua_lock(L); + name = aux_upvalue(index2adr(L, funcindex), n, &val); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + StkId fi; + lua_lock(L); + fi = index2adr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, clvalue(fi), L->top); + } + lua_unlock(L); + return name; +} + diff --git a/source/lua/lapi.h b/source/lua/lapi.h new file mode 100644 index 0000000..2c3fab2 --- /dev/null +++ b/source/lua/lapi.h @@ -0,0 +1,16 @@ +/* +** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + +#endif diff --git a/source/lua/lauxlib.c b/source/lua/lauxlib.c new file mode 100644 index 0000000..10f14e2 --- /dev/null +++ b/source/lua/lauxlib.c @@ -0,0 +1,652 @@ +/* +** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" + + +#define FREELIST_REF 0 /* free list of references */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + } + luaL_typerror(L, ud, tname); /* else error */ + return NULL; /* to avoid warnings */ +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tolstring(L, narg, len); + if (!s) tag_error(L, narg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, narg, def); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l) { + luaI_openlib(L, libname, l, 0); +} + + +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l->name; l++) size++; + return size; +} + + +LUALIB_API void luaI_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + if (libname) { + int size = libsize(l); + /* check whether lib already exists */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); + lua_getfield(L, -1, libname); /* get _LOADED[libname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, libname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + for (i=0; ifunc, nup); + lua_setfield(L, -(nup+2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +#if defined(LUA_COMPAT_GETN) + +static int checkint (lua_State *L, int topop) { + int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_pop(L, 1); /* remove nil */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ + } +} + + +LUALIB_API void luaL_setn (lua_State *L, int t, int n) { + t = abs_index(L, t); + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushinteger(L, n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushinteger(L, n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +LUALIB_API int luaL_getn (lua_State *L, int t) { + int n; + t = abs_index(L, t); + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + return (int)lua_objlen(L, t); +} + +#endif + +/* }====================================================== */ + + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after `p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +LUALIB_API const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_addchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl; + const char *s = lua_tolstring(L, -1, &vl); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, s, vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ + } + else { /* no free elements */ + ref = (int)lua_objlen(L, t); + ref++; /* create new reference */ + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int extraline; + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (lf->extraline) { + lf->extraline = 0; + *size = 1; + return "\n"; + } + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + lf.extraline = 0; + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + c = getc(lf.f); + if (c == '#') { /* Unix exec. file? */ + lf.extraline = 1; + while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ + if (c == '\n') c = getc(lf.f); + } + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + /* skip eventual `#!...' */ + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + lf.extraline = 0; + } + ungetc(c, lf.f); + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + + +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + + + +/* }====================================================== */ + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; + (void)osize; + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + diff --git a/source/lua/lauxlib.h b/source/lua/lauxlib.h new file mode 100644 index 0000000..3425823 --- /dev/null +++ b/source/lua/lauxlib.h @@ -0,0 +1,174 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) +#define luaL_setn(L,i,j) ((void)0) /* no op! */ +#endif + +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + + +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) + + +#define luaL_reg luaL_Reg + +#endif + + diff --git a/source/lua/lbaselib.c b/source/lua/lbaselib.c new file mode 100644 index 0000000..2ab550b --- /dev/null +++ b/source/lua/lbaselib.c @@ -0,0 +1,653 @@ +/* +** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, LUA_QL("tostring") " must return a string to " + LUA_QL("print")); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L, int opt) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L, 1); + if (lua_iscfunction(L, -1)) /* is a C function? */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ + else + lua_getfenv(L, -1); + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); + lua_setfenv(L, -2); + return 0; + } + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) + luaL_error(L, + LUA_QL("setfenv") " cannot change environment of given object"); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushinteger(L, lua_getgccount(L)); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; + int o = luaL_checkoption(L, 1, "collect", opts); + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, optsnum[o], ex); + switch (optsnum[o]) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushnumber(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, luaL_typename(L, 1)); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + i++; /* next value */ + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); + return (lua_isnil(L, -1)) ? 0 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushinteger(L, 0); /* and initial value */ + return 3; +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +/* +** Reader for generic `load' function: `lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)ud; /* to avoid warnings */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + *size = 0; + return NULL; + } + else if (lua_isstring(L, -1)) { + lua_replace(L, 3); /* save string in a reserved stack slot */ + return lua_tolstring(L, 3, size); + } + else luaL_error(L, "reader function must return a string"); + return NULL; /* to avoid warnings */ +} + + +static int luaB_load (lua_State *L) { + int status; + const char *cname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ + status = lua_load(L, generic_reader, NULL, cname); + return load_aux(L, status); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + if (luaL_loadfile(L, fname) != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +static int luaB_unpack (lua_State *L) { + int i, e, n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); + if (i > e) return 0; /* empty range */ + n = e - i + 1; /* number of elements */ + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + int i = luaL_checkint(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - i; + } +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + break; + case LUA_TSTRING: + lua_pushvalue(L, 1); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); + break; + } + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"gcinfo", luaB_gcinfo}, + {"getfenv", luaB_getfenv}, + {"getmetatable", luaB_getmetatable}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"loadstring", luaB_loadstring}, + {"next", luaB_next}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setfenv", luaB_setfenv}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"unpack", luaB_unpack}, + {"xpcall", luaB_xpcall}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +#define CO_RUN 0 /* running */ +#define CO_SUS 1 /* suspended */ +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ +#define CO_DEAD 3 + +static const char *const statnames[] = + {"running", "suspended", "normal", "dead"}; + +static int costatus (lua_State *L, lua_State *co) { + if (L == co) return CO_RUN; + switch (lua_status(co)) { + case LUA_YIELD: + return CO_SUS; + case 0: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + return CO_NOR; /* it is running */ + else if (lua_gettop(co) == 0) + return CO_DEAD; + else + return CO_SUS; /* initial state */ + } + default: /* some error occured */ + return CO_DEAD; + } +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + lua_pushstring(L, statnames[costatus(L, co)]); + return 1; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status = costatus(L, co); + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + if (status != CO_SUS) { + lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + lua_setlevel(L, co); + status = lua_resume(co, narg); + if (status == 0 || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_corunning (lua_State *L) { + if (lua_pushthread(L)) + lua_pushnil(L); /* main thread is not a coroutine */ + return 1; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {NULL, NULL} +}; + +/* }====================================================== */ + + +static void auxopen (lua_State *L, const char *name, + lua_CFunction f, lua_CFunction u) { + lua_pushcfunction(L, u); + lua_pushcclosure(L, f, 1); + lua_setfield(L, -2, name); +} + + +static void base_open (lua_State *L) { + /* set global _G */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setglobal(L, "_G"); + /* open lib into global table */ + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ + /* `ipairs' and `pairs' need auxiliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); + /* `newproxy' needs a weaktable as upvalue */ + lua_createtable(L, 0, 1); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_setglobal(L, "newproxy"); /* set global `newproxy' */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_register(L, LUA_COLIBNAME, co_funcs); + return 2; +} + diff --git a/source/lua/lcode.c b/source/lua/lcode.c new file mode 100644 index 0000000..679cb9c --- /dev/null +++ b/source/lua/lcode.c @@ -0,0 +1,831 @@ +/* +** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int isnumeral(expdesc *e) { + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + if (fs->pc == 0) { /* function start? */ + if (from >= fs->nactvar) + return; /* positions are already clean */ + } + else { + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pto = GETARG_B(*previous); + if (pfrom <= from && from <= pto+1) { /* can connect both? */ + if (from+n-1 > pto) + SETARG_B(*previous, from+n-1); + return; + } + } + } + } + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + + +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.s.info); +} + + +static int addk (FuncState *fs, TValue *k, TValue *v) { + lua_State *L = fs->L; + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; + if (ttisnumber(idx)) { + lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); + return cast_int(nvalue(idx)); + } + else { /* constant not found; create a new entry */ + setnvalue(idx, cast_num(fs->nk)); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[fs->nk], v); + luaC_barrier(L, f, v); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + + +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->L, &k, fs->h); + return addk(fs, &k, &v); +} + + +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.s.info = GETARG_A(getcode(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->u.s.aux); + freereg(fs, e->u.s.info); + e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + break; + } + case VKNUM: { + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.s.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ + if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.s.info); /* put value on it */ + return e->u.s.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.s.info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VKNUM: + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); + } + else break; + } + case VK: { + if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e->u.s.info); + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.s.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, ex); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int func; + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + func = fs->freereg; + luaK_reserveregs(fs, 2); + luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->u.s.info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.s.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + + +static void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VJMP: { + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->u.s.aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + v1 = e1->u.nval; + v2 = e2->u.nval; + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; + case OP_MUL: r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_nummod(v1, v2); break; + case OP_POW: r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; + int o1 = luaK_exp2RK(fs, e1); + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } + else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + } +} + + +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, + expdesc *e2) { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.s.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_UNM, e, &e2); + break; + } + case OPR_NOT: codenot(fs, e); break; + case OPR_LEN: { + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.s.info); + e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2); + } + break; + } + case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; + case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; + case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; + case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; + case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; + case OPR_POW: codearith(fs, OP_POW, e1, e2); break; + case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; + case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; + case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; + case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; + case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; + case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +static int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + + +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + } + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/source/lua/lcode.h b/source/lua/lcode.h new file mode 100644 index 0000000..b941c60 --- /dev/null +++ b/source/lua/lcode.h @@ -0,0 +1,76 @@ +/* +** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/source/lua/ldblib.c b/source/lua/ldblib.c new file mode 100644 index 0000000..2027eda --- /dev/null +++ b/source/lua/ldblib.c @@ -0,0 +1,398 @@ +/* +** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_pushboolean(L, lua_setmetatable(L, 1)); + return 1; +} + + +static int db_getfenv (lua_State *L) { + luaL_checkany(L, 1); + lua_getfenv(L, 1); + return 1; +} + + +static int db_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + if (lua_setfenv(L, 1) == 0) + luaL_error(L, LUA_QL("setfenv") + " cannot change environment of given object"); + return 1; +} + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, i); +} + + +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; + } +} + + +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) { + lua_pushvalue(L, -2); + lua_remove(L, -3); + } + else + lua_xmove(L1, L, 1); + lua_setfield(L, -2, fname); +} + + +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnSu"); + if (lua_isnumber(L, arg+1)) { + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, arg+1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, arg+1); + lua_xmove(L, L1, 1); + } + else + return luaL_argerror(L, arg+1, "function or level expected"); + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_createtable(L, 0, 2); + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) + settabsi(L, "nups", ar.nups); + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); + if (name) { + lua_xmove(L1, L, 1); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + lua_xmove(L, L1, 1); + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, L); + lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static void gethooktable (lua_State *L) { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + lua_pop(L, 1); /* remove hook table */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) { + fputs(lua_tostring(L, -1), stderr); + fputs("\n", stderr); + } + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int db_errorfb (lua_State *L) { + int level; + int firstpart = 1; /* still before eventual `...' */ + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (lua_isnumber(L, arg+2)) { + level = (int)lua_tointeger(L, arg+2); + lua_pop(L, 1); + } + else + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ + if (lua_gettop(L) == arg) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L1, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L1, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, " in function " LUA_QS, ar.name); + else { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + lua_concat(L, lua_gettop(L) - arg); + } + lua_concat(L, lua_gettop(L) - arg); + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getfenv", db_getfenv}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"setfenv", db_setfenv}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_register(L, LUA_DBLIBNAME, dblib); + return 1; +} + diff --git a/source/lua/ldebug.c b/source/lua/ldebug.c new file mode 100644 index 0000000..50ad3d3 --- /dev/null +++ b/source/lua/ldebug.c @@ -0,0 +1,638 @@ +/* +** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + + +#define ldebug_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (lua_State *L, CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci == L->ci) + ci->savedpc = L->savedpc; + return pcRel(ci->savedpc, ci_func(ci)->l.p); +} + + +static int currentline (lua_State *L, CallInfo *ci) { + int pc = currentpc(L, ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + lua_lock(L); + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (f_isLua(ci)) /* Lua function? */ + level -= ci->tailcalls; /* skip lost tail calls */ + } + if (level == 0 && ci > L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = cast_int(ci - L->base_ci); + } + else if (level < 0) { /* level is of a lost tail call? */ + status = 1; + ar->i_ci = 0; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n) { + const char *name; + Proto *fp = getluaproto(ci); + if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) + return name; /* is a local variable in a Lua function */ + else { + StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; + if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + return "(*temporary)"; + else + return NULL; + } +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + luaA_pushobject(L, ci->base + (n - 1)); + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + setobjs2s(L, ci->base + (n - 1), L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->linedefined; + ar->lastlinedefined = cl->l.p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void info_tailcall (lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->lastlinedefined = ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (f == NULL || f->c.isC) { + setnilvalue(L->top); + } + else { + Table *t = luaH_new(L, 0, 0); + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; il.p->sizelineinfo; i++) + setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + if (f == NULL) { + info_tailcall(ar); + return status; + } + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(L, ci) : -1; + break; + } + case 'u': { + ar->nups = f->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *f = NULL; + CallInfo *ci = NULL; + lua_lock(L); + if (*what == '>') { + StkId func = L->top - 1; + luai_apicheck(L, ttisfunction(func)); + what++; /* skip the '>' */ + f = clvalue(func); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->func)); + f = clvalue(ci->func); + } + status = auxgetinfo(L, what, ar, f, ci); + if (strchr(what, 'f')) { + if (f == NULL) setnilvalue(L->top); + else setclvalue(L, L->top, f); + incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, f); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + check(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) + +int luaG_checkopenop (Instruction i) { + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: + case OP_SETLIST: { + check(GETARG_B(i) == 0); + return 1; + } + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { + switch (mode) { + case OpArgN: check(r == 0); break; + case OpArgU: break; + case OpArgR: checkreg(pt, r); break; + case OpArgK: + check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); + break; + } + return 1; +} + + +static Instruction symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + check(op < NUM_OPCODES); + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + check(checkArgMode(pt, b, getBMode(op))); + check(checkArgMode(pt, c, getCMode(op))); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (getBMode(op) == OpArgK) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + if (getBMode(op) == OpArgR) { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + if (dest > 0) { + int j; + /* check that it does not jump to a setlist count; this + is tricky, because the count from a previous setlist may + have the same value of an invalid setlist; so, we must + go all the way back to the first of them (if any) */ + for (j = 0; j < dest; j++) { + Instruction d = pt->code[dest-1-j]; + if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; + } + /* if 'j' is even, previous value is not a setlist (even if + it looks like one) */ + check((j&1) == 0); + } + } + break; + } + } + if (testAMode(op)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testTMode(op)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + if (c == 1) { /* does it jump? */ + check(pc+2 < pt->sizecode); /* check its jump */ + check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || + GETARG_C(pt->code[pc+1]) != 0); + } + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + check(b < c); /* at least two operands */ + break; + } + case OP_TFORLOOP: { + check(c >= 1); /* at least one result (control variable) */ + checkreg(pt, a+2+c); /* space for results */ + if (reg >= a+2) last = pc; /* affect all regs above its base */ + break; + } + case OP_FORLOOP: + case OP_FORPREP: + checkreg(pt, a+3); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + if (b > 0) checkreg(pt, a + b); + if (c == 0) { + pc++; + check(pc < pt->sizecode - 1); + } + break; + } + case OP_CLOSURE: { + int nup, j; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (j = 1; j <= nup; j++) { + OpCode op1 = GET_OPCODE(pt->code[pc + j]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + if (reg != NO_REG) /* tracing? */ + pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case OP_VARARG: { + check((pt->is_vararg & VARARG_ISVARARG) && + !(pt->is_vararg & VARARG_NEEDSARG)); + b--; + if (b == LUA_MULTRET) check(checkopenop(pt, pc)); + checkreg(pt, a+b-1); + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return (symbexec(pt, pt->sizecode, NO_REG) != 0); +} + + +static const char *kname (Proto *p, int c) { + if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) + return svalue(&p->k[INDEXK(c)]); + else + return "?"; +} + + +static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, + const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(L, ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(L, ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_GETUPVAL: { + int u = GETARG_B(i); /* upvalue index */ + *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + return "upvalue"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(L, ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_TFORLOOP) + return getobjname(L, ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; + lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); + return 0; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(L, ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +void luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/source/lua/ldebug.h b/source/lua/ldebug.h new file mode 100644 index 0000000..ba28a97 --- /dev/null +++ b/source/lua/ldebug.h @@ -0,0 +1,33 @@ +/* +** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaG_errormsg (lua_State *L); +LUAI_FUNC int luaG_checkcode (const Proto *pt); +LUAI_FUNC int luaG_checkopenop (Instruction i); + +#endif diff --git a/source/lua/ldo.c b/source/lua/ldo.c new file mode 100644 index 0000000..d1bf786 --- /dev/null +++ b/source/lua/ldo.c @@ -0,0 +1,519 @@ +/* +** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +static void restore_stack_limit (lua_State *L) { + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ + int inuse = cast_int(L->ci - L->base_ci); + if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUAI_MAXCALLS); + } +} + + +static void resetstack (lua_State *L, int status) { + L->ci = L->base_ci; + L->base = L->ci->base; + luaF_close(L, L->base); /* close eventual pending closures */ + luaD_seterrorobj(L, status, L->base); + L->nCcalls = L->baseCcalls; + L->allowhook = 1; + restore_stack_limit(L); + L->errfunc = 0; + L->errorJmp = NULL; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + LUAI_THROW(L, L->errorJmp); + } + else { + L->status = cast_byte(errcode); + if (G(L)->panic) { + resetstack(L, errcode); + lua_unlock(L); + G(L)->panic(L); + } + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack+newsize; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = newsize; + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci - 1; +} + + +void luaD_growstack (lua_State *L, int n) { + if (n <= L->stacksize) /* double size is enough? */ + luaD_reallocstack(L, 2*L->stacksize); + else + luaD_reallocstack(L, L->stacksize + n); +} + + +static CallInfo *growCI (lua_State *L) { + if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUAI_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } + return ++L->ci; +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = cast_int(L->ci - L->base_ci); + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + lua_assert(L->ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + Table *htab = NULL; + StkId base, fixed; + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); +#if defined(LUA_COMPAT_VARARG) + if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ + int nvar = actual - nfixargs; /* number of extra arguments */ + lua_assert(p->is_vararg & VARARG_HASARG); + luaC_checkGC(L); + luaD_checkstack(L, p->maxstacksize); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; itop - nvar + i); + /* store counter in field `n' */ + setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); + } +#endif + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; itop++, fixed+i); + setnilvalue(fixed+i); + } + /* add `arg' parameter */ + if (htab) { + sethvalue(L, L->top++, htab); + lua_assert(iswhite(obj2gco(htab))); + } + return base; +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ + return func; +} + + + +#define inc_ci(L) \ + ((L->ci == L->end_ci) ? growCI(L) : \ + (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) + + +int luaD_precall (lua_State *L, StkId func, int nresults) { + LClosure *cl; + ptrdiff_t funcr; + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + funcr = savestack(L, func); + cl = &clvalue(func)->l; + L->ci->savedpc = L->savedpc; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; + if (L->top > base + p->numparams) + L->top = base + p->numparams; + } + else { /* vararg function */ + int nargs = cast_int(L->top - func) - 1; + base = adjust_varargs(L, p, nargs); + func = restorestack(L, funcr); /* previous call may change the stack */ + } + ci = inc_ci(L); /* now `enter' new function */ + ci->func = func; + L->base = ci->base = base; + ci->top = L->base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + L->savedpc = p->code; /* starting point */ + ci->tailcalls = 0; + ci->nresults = nresults; + for (st = L->top; st < ci->top; st++) + setnilvalue(st); + L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) { + L->savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_callhook(L, LUA_HOOKCALL, -1); + L->savedpc--; /* correct 'pc' */ + } + return PCRLUA; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = inc_ci(L); /* now `enter' new function */ + ci->func = restorestack(L, funcr); + L->base = ci->base = ci->func + 1; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->nresults = nresults; + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*curr_func(L)->c.f)(L); /* do the actual call */ + lua_lock(L); + if (n < 0) /* yielding? */ + return PCRYIELD; + else { + luaD_poscall(L, L->top - n); + return PCRC; + } + } +} + + +static StkId callrethooks (lua_State *L, StkId firstResult) { + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ + luaD_callhook(L, LUA_HOOKRET, -1); + if (f_isLua(L->ci)) { /* Lua function? */ + while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + ci = L->ci--; + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->base = (ci - 1)->base; /* restore base */ + L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ + /* move results to correct place */ + for (i = wanted; i != 0 && firstResult < L->top; i--) + setobjs2s(L, res++, firstResult++); + while (i-- > 0) + setnilvalue(res++); + L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ + luaV_execute(L, 1); /* call it */ + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (L->status == 0) { /* start coroutine? */ + lua_assert(ci == L->base_ci && firstArg > L->base); + if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) + return; + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = 0; + if (!f_isLua(ci)) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); + if (luaD_poscall(L, firstArg)) /* complete it... */ + L->top = L->ci->top; /* and correct top if not multiple results */ + } + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; + } + luaV_execute(L, cast_int(L->ci - L->base_ci)); +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L, L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lua_lock(L); + if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) + return resume_error(L, "cannot resume non-suspended coroutine"); + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow"); + luai_userstateresume(L, nargs); + lua_assert(L->errfunc == 0); + L->baseCcalls = ++L->nCcalls; + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status != 0) { /* error? */ + L->status = cast_byte(status); /* mark thread as `dead' */ + luaD_seterrorobj(L, status, L->top); + L->ci->top = L->top; + } + else { + lua_assert(L->nCcalls == L->baseCcalls); + status = L->status; + } + --L->nCcalls; + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + luai_userstateyield(L, nresults); + lua_lock(L); + if (L->nCcalls > L->baseCcalls) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + L->base = L->top - nresults; /* protect stack slots below */ + L->status = LUA_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != 0) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close eventual pending closures */ + luaD_seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->savedpc = L->ci->savedpc; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + const char *name; +}; + +static void f_parser (lua_State *L, void *ud) { + int i; + Proto *tf; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = luaZ_lookahead(p->z); + luaC_checkGC(L); + tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, + &p->buff, p->name); + cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); + cl->l.p = tf; + for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ + cl->l.upvals[i] = luaF_newupval(L); + setclvalue(L, L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { + struct SParser p; + int status; + p.z = z; p.name = name; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + return status; +} + + diff --git a/source/lua/ldo.h b/source/lua/ldo.h new file mode 100644 index 0000000..98fddac --- /dev/null +++ b/source/lua/ldo.h @@ -0,0 +1,57 @@ +/* +** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* results from luaD_precall */ +#define PCRLUA 0 /* initiated a call to a Lua function */ +#define PCRC 1 /* did a call to a C function */ +#define PCRYIELD 2 /* C funtion yielded */ + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); +LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); + +LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); + +#endif + diff --git a/source/lua/ldump.c b/source/lua/ldump.c new file mode 100644 index 0000000..c9d3d48 --- /dev/null +++ b/source/lua/ldump.c @@ -0,0 +1,164 @@ +/* +** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +typedef struct { + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; +} DumpState; + +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status==0) + { + lua_unlock(D->L); + D->status=(*D->writer)(D->L,b,size,D->data); + lua_lock(D->L); + } +} + +static void DumpChar(int y, DumpState* D) +{ + char x=(char)y; + DumpVar(x,D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void* b, int n, size_t size, DumpState* D) +{ + DumpInt(n,D); + DumpMem(b,n,size,D); +} + +static void DumpString(const TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + { + size_t size=0; + DumpVar(size,D); + } + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; ik[i]; + DumpChar(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; ip[i],f->source,D); +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo,n,sizeof(int),D); + n= (D->strip) ? 0 : f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } + n= (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p || D->strip) ? NULL : f->source,D); + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->nups,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + char h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); +} + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) +{ + DumpState D; + D.L=L; + D.writer=w; + D.data=data; + D.strip=strip; + D.status=0; + DumpHeader(&D); + DumpFunction(f,NULL,&D); + return D.status; +} diff --git a/source/lua/lfunc.c b/source/lua/lfunc.c new file mode 100644 index 0000000..813e88f --- /dev/null +++ b/source/lua/lfunc.c @@ -0,0 +1,174 @@ +/* +** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c +#define LUA_CORE + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.env = e; + c->c.nupvalues = cast_byte(nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.env = e; + c->l.nupvalues = cast_byte(nelems); + while (nelems--) c->l.upvals[nelems] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = luaM_new(L, UpVal); + luaC_link(L, obj2gco(uv), LUA_TUPVAL); + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *uv; + while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { + lua_assert(p->v != &p->u.value); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } + pp = &p->next; + } + uv = luaM_new(L, UpVal); /* not found: create a new one */ + uv->tt = LUA_TUPVAL; + uv->marked = luaC_white(g); + uv->v = level; /* current value lives in the stack */ + uv->next = *pp; /* chain it in the proper position */ + *pp = obj2gco(uv); + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + return uv; +} + + +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + global_State *g = G(L); + while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o) && uv->v != &uv->u.value); + L->openupval = uv->next; /* remove from `open' list */ + if (isdead(g, o)) + luaF_freeupval(L, uv); /* free upvalue */ + else { + unlinkupval(uv); + setobj(L, &uv->u.value, uv->v); + uv->v = &uv->u.value; /* now current value lives here */ + luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TValue); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_free(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_freemem(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/source/lua/lfunc.h b/source/lua/lfunc.h new file mode 100644 index 0000000..a68cf51 --- /dev/null +++ b/source/lua/lfunc.h @@ -0,0 +1,34 @@ +/* +** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); +LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/source/lua/lgc.c b/source/lua/lgc.c new file mode 100644 index 0000000..e909c79 --- /dev/null +++ b/source/lua/lgc.c @@ -0,0 +1,710 @@ +/* +** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 + + +#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) + +#define makewhite(g,x) \ + ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) + +#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) + +#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) + + +#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) + + +#define KEYWEAK bitmask(KEYWEAKBIT) +#define VALUEWEAK bitmask(VALUEWEAKBIT) + + + +#define markvalue(g,o) { checkconsistency(o); \ + if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + + +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) + + +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ +} + + +static void reallymarkobject (global_State *g, GCObject *o) { + lua_assert(iswhite(o) && !isdead(g, o)); + white2gray(o); + switch (o->gch.tt) { + case LUA_TSTRING: { + return; + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + gray2black(o); /* udata are never gray */ + if (mt) markobject(g, mt); + markobject(g, gco2u(o)->env); + return; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v == &uv->u.value) /* closed? */ + gray2black(o); /* open upvalues are never black */ + return; + } + case LUA_TFUNCTION: { + gco2cl(o)->c.gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTABLE: { + gco2h(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + break; + } + default: lua_assert(0); + } +} + + +static void marktmu (global_State *g) { + GCObject *u = g->tmudata; + if (u) { + do { + u = u->gch.next; + makewhite(g, u); /* may be marked, if left from previous GC */ + reallymarkobject(g, u); + } while (u != g->tmudata); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L, int all) { + global_State *g = G(L); + size_t deadmem = 0; + GCObject **p = &g->mainthread->next; + GCObject *curr; + while ((curr = *p) != NULL) { + if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) + p = &curr->gch.next; /* don't bother with them */ + else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { + markfinalized(gco2u(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gco2u(curr)); + markfinalized(gco2u(curr)); + *p = curr->gch.next; + /* link `curr' at the end of `tmudata' list */ + if (g->tmudata == NULL) /* list is empty? */ + g->tmudata = curr->gch.next = curr; /* creates a circular list */ + else { + curr->gch.next = g->tmudata->gch.next; + g->tmudata->gch.next = curr; + g->tmudata = curr; + } + } + } + return deadmem; +} + + +static int traversetable (global_State *g, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TValue *mode; + if (h->metatable) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast_byte((weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + h->gclist = g->weak; /* must be cleared after GC, ... */ + g->weak = obj2gco(h); /* ... so put in the appropriate list */ + } + } + if (weakkey && weakvalue) return 1; + if (!weakvalue) { + i = h->sizearray; + while (i--) + markvalue(g, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + if (!weakkey) markvalue(g, gkey(n)); + if (!weakvalue) markvalue(g, gval(n)); + } + } + return weakkey || weakvalue; +} + + +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ +static void traverseproto (global_State *g, Proto *f) { + int i; + if (f->source) stringmark(f->source); + for (i=0; isizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i=0; isizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; isizep; i++) { /* mark nested protos */ + if (f->p[i]) + markobject(g, f->p[i]); + } + for (i=0; isizelocvars; i++) { /* mark local-variable names */ + if (f->locvars[i].varname) + stringmark(f->locvars[i].varname); + } +} + + + +static void traverseclosure (global_State *g, Closure *cl) { + markobject(g, cl->c.env); + if (cl->c.isC) { + int i; + for (i=0; ic.nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markobject(g, cl->l.p); + for (i=0; il.nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->l.upvals[i]); + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ + int s_used = cast_int(max - L->stack); /* part of stack in use */ + if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ + return; /* do not touch the stacks */ + if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + condhardstacktests(luaD_reallocCI(L, ci_used + 1)); + if (4*s_used < L->stacksize && + 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + condhardstacktests(luaD_reallocstack(L, s_used)); +} + + +static void traversestack (global_State *g, lua_State *l) { + StkId o, lim; + CallInfo *ci; + markvalue(g, gt(l)); + lim = l->top; + for (ci = l->base_ci; ci <= l->ci; ci++) { + lua_assert(ci->top <= l->stack_last); + if (lim < ci->top) lim = ci->top; + } + for (o = l->stack; o < l->top; o++) + markvalue(g, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(l, lim); +} + + +/* +** traverse one gray object, turning it to black. +** Returns `quantity' traversed. +*/ +static l_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->gch.tt) { + case LUA_TTABLE: { + Table *h = gco2h(o); + g->gray = h->gclist; + if (traversetable(g, h)) /* table is weak? */ + black2gray(o); /* keep it gray */ + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * sizenode(h); + } + case LUA_TFUNCTION: { + Closure *cl = gco2cl(o); + g->gray = cl->c.gclist; + traverseclosure(g, cl); + return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : + sizeLclosure(cl->l.nupvalues); + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; + th->gclist = g->grayagain; + g->grayagain = o; + black2gray(o); + traversestack(g, th); + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->size_ci; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; + traverseproto(g, p); + return sizeof(Proto) + sizeof(Instruction) * p->sizecode + + sizeof(Proto *) * p->sizep + + sizeof(TValue) * p->sizek + + sizeof(int) * p->sizelineinfo + + sizeof(LocVar) * p->sizelocvars + + sizeof(TString *) * p->sizeupvalues; + } + default: lua_assert(0); return 0; + } +} + + +static size_t propagateall (global_State *g) { + size_t m = 0; + while (g->gray) m += propagatemark(g); + return m; +} + + +/* +** The next function tells whether a key or value can be cleared from +** a weak table. Non-collectable objects are never removed from weak +** tables. Strings behave as `values', so are never removed too. for +** other objects: if really collected, cannot keep them; for userdata +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (const TValue *o, int iskey) { + if (!iscollectable(o)) return 0; + if (ttisstring(o)) { + stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + return iswhite(gcvalue(o)) || + (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +} + + +/* +** clear collected entries from weaktables +*/ +static void cleartable (GCObject *l) { + while (l) { + Table *h = gco2h(l); + int i = h->sizearray; + lua_assert(testbit(h->marked, VALUEWEAKBIT) || + testbit(h->marked, KEYWEAKBIT)); + if (testbit(h->marked, VALUEWEAKBIT)) { + while (i--) { + TValue *o = &h->array[i]; + if (iscleared(o, 0)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n)) && /* non-empty entry? */ + (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* remove entry from table */ + } + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2h(o)); break; + case LUA_TTHREAD: { + lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); + luaE_freethread(L, gco2th(o)); + break; + } + case LUA_TSTRING: { + G(L)->strt.nuse--; + luaM_freemem(L, o, sizestring(gco2ts(o))); + break; + } + case LUA_TUSERDATA: { + luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + } + default: lua_assert(0); + } +} + + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) + + +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + GCObject *curr; + global_State *g = G(L); + int deadmask = otherwhite(g); + while ((curr = *p) != NULL && count-- > 0) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ + lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); + makewhite(g, curr); /* make it white (for next cycle) */ + p = &curr->gch.next; + } + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); + *p = curr->gch.next; + if (curr == g->rootgc) /* is the first element of the list? */ + g->rootgc = curr->gch.next; /* adjust first */ + freeobj(L, curr); + } + } + return p; +} + + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + /* check size of string hash */ + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && + g->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, g->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&g->buff) / 2; + luaZ_resizebuffer(L, &g->buff, newsize); + } +} + + +static void GCTM (lua_State *L) { + global_State *g = G(L); + GCObject *o = g->tmudata->gch.next; /* get first element */ + Udata *udata = rawgco2u(o); + const TValue *tm; + /* remove udata from `tmudata' */ + if (o == g->tmudata) /* last element? */ + g->tmudata = NULL; + else + g->tmudata->gch.next = udata->uv.next; + udata->uv.next = g->mainthread->next; /* return it to `root' list */ + g->mainthread->next = o; + makewhite(g, o); + tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + lu_byte oldah = L->allowhook; + lu_mem oldt = g->GCthreshold; + L->allowhook = 0; /* stop debug hooks during GC tag method */ + g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ + setobj2s(L, L->top, tm); + setuvalue(L, L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + L->allowhook = oldah; /* restore hooks */ + g->GCthreshold = oldt; /* restore threshold */ + } +} + + +/* +** Call all GC tag methods +*/ +void luaC_callGCTM (lua_State *L) { + while (G(L)->tmudata) + GCTM(L); +} + + +void luaC_freeall (lua_State *L) { + global_State *g = G(L); + int i; + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); +} + + +static void markmt (global_State *g) { + int i; + for (i=0; imt[i]) markobject(g, g->mt[i]); +} + + +/* mark root set */ +static void markroot (lua_State *L) { + global_State *g = G(L); + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + markobject(g, g->mainthread); + /* make global table be traversed before main stack */ + markvalue(g, gt(g->mainthread)); + markvalue(g, registry(L)); + markmt(g); + g->gcstate = GCSpropagate; +} + + +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +static void atomic (lua_State *L) { + global_State *g = G(L); + size_t udsize; /* total size of userdata to be finalized */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + /* traverse objects cautch by write barrier and by 'remarkupvals' */ + propagateall(g); + /* remark weak tables */ + g->gray = g->weak; + g->weak = NULL; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + markmt(g); /* mark basic metatables (again) */ + propagateall(g); + /* remark gray again */ + g->gray = g->grayagain; + g->grayagain = NULL; + propagateall(g); + udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ + marktmu(g); /* mark `preserved' userdata */ + udsize += propagateall(g); /* remark, to propagate `preserveness' */ + cleartable(g->weak); /* remove collected objects from weak tables */ + /* flip current white */ + g->currentwhite = cast_byte(otherwhite(g)); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gcstate = GCSsweepstring; + g->estimate = g->totalbytes - udsize; /* first estimate */ +} + + +static l_mem singlestep (lua_State *L) { + global_State *g = G(L); + /*lua_checkmemory(L);*/ + switch (g->gcstate) { + case GCSpause: { + markroot(L); /* start a new collection */ + return 0; + } + case GCSpropagate: { + if (g->gray) + return propagatemark(g); + else { /* no more `gray' objects */ + atomic(L); /* finish mark phase */ + return 0; + } + } + case GCSsweepstring: { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPCOST; + } + case GCSsweep: { + lu_mem old = g->totalbytes; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + if (*g->sweepgc == NULL) { /* nothing more to sweep? */ + checkSizes(L); + g->gcstate = GCSfinalize; /* end sweep phase */ + } + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPMAX*GCSWEEPCOST; + } + case GCSfinalize: { + if (g->tmudata) { + GCTM(L); + if (g->estimate > GCFINALIZECOST) + g->estimate -= GCFINALIZECOST; + return GCFINALIZECOST; + } + else { + g->gcstate = GCSpause; /* end collection */ + g->gcdept = 0; + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +void luaC_step (lua_State *L) { + global_State *g = G(L); + l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ + g->gcdept += g->totalbytes - g->GCthreshold; + do { + lim -= singlestep(L); + if (g->gcstate == GCSpause) + break; + } while (lim > 0); + if (g->gcstate != GCSpause) { + if (g->gcdept < GCSTEPSIZE) + g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ + else { + g->gcdept -= GCSTEPSIZE; + g->GCthreshold = g->totalbytes; + } + } + else { + setthreshold(g); + } +} + + +void luaC_fullgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate <= GCSpropagate) { + /* reset sweep marks to sweep all elements (returning them to white) */ + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + /* reset other collector lists */ + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->gcstate = GCSsweepstring; + } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); + /* finish any pending sweep phase */ + while (g->gcstate != GCSfinalize) { + lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); + singlestep(L); + } + markroot(L); + while (g->gcstate != GCSpause) { + singlestep(L); + } + setthreshold(g); +} + + +void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + lua_assert(ttype(&o->gch) != LUA_TTABLE); + /* must keep invariant? */ + if (g->gcstate == GCSpropagate) + reallymarkobject(g, v); /* restore invariant */ + else /* don't mind */ + makewhite(g, o); /* mark as white just to avoid other barriers */ +} + + +void luaC_barrierback (lua_State *L, Table *t) { + global_State *g = G(L); + GCObject *o = obj2gco(t); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + black2gray(o); /* make table gray (again) */ + t->gclist = g->grayagain; + g->grayagain = o; +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + global_State *g = G(L); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + + +void luaC_linkupval (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = obj2gco(uv); + o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ + g->rootgc = o; + if (isgray(o)) { + if (g->gcstate == GCSpropagate) { + gray2black(o); /* closed upvalues need barrier */ + luaC_barrier(L, uv, uv->v); + } + else { /* sweep phase: sweep it (turning it into white) */ + makewhite(g, o); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + } + } +} + diff --git a/source/lua/lgc.h b/source/lua/lgc.h new file mode 100644 index 0000000..5a8dc60 --- /dev/null +++ b/source/lua/lgc.h @@ -0,0 +1,110 @@ +/* +** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpause 0 +#define GCSpropagate 1 +#define GCSsweepstring 2 +#define GCSsweep 3 +#define GCSfinalize 4 + + +/* +** some userful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) +#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) +#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) +#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) + + + +/* +** Layout for bit use in `marked' field: +** bit 0 - object is white (type 0) +** bit 1 - object is white (type 1) +** bit 2 - object is black +** bit 3 - for userdata: has been finalized +** bit 3 - for tables: has weak keys +** bit 4 - for tables: has weak values +** bit 5 - object is fixed (should not be collected) +** bit 6 - object is "super" fixed (only the main thread) +*/ + + +#define WHITE0BIT 0 +#define WHITE1BIT 1 +#define BLACKBIT 2 +#define FINALIZEDBIT 3 +#define KEYWEAKBIT 3 +#define VALUEWEAKBIT 4 +#define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) (!isblack(x) && !iswhite(x)) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) + +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +#define luaC_checkGC(L) { \ + condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ + if (G(L)->totalbytes >= G(L)->GCthreshold) \ + luaC_step(L); } + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ + luaC_barrierback(L,t); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarriert(L,t,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } + +LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); +LUAI_FUNC void luaC_callGCTM (lua_State *L); +LUAI_FUNC void luaC_freeall (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_fullgc (lua_State *L); +LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); +LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); + + +#endif diff --git a/source/lua/linit.c b/source/lua/linit.c new file mode 100644 index 0000000..c1f90df --- /dev/null +++ b/source/lua/linit.c @@ -0,0 +1,38 @@ +/* +** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ +** Initialization of libraries for lua.c +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +static const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } +} + diff --git a/source/lua/liolib.c b/source/lua/liolib.c new file mode 100644 index 0000000..649f9a5 --- /dev/null +++ b/source/lua/liolib.c @@ -0,0 +1,556 @@ +/* +** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/source/lua/llex.c b/source/lua/llex.c new file mode 100644 index 0000000..88c6790 --- /dev/null +++ b/source/lua/llex.c @@ -0,0 +1,463 @@ +/* +** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "", "", "", "", + NULL +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (b->n + 1 > b->buffsize) { + size_t newsize; + if (b->buffsize >= MAX_SIZET/2) + luaX_lexerror(ls, "lexical element too long", 0); + newsize = b->buffsize * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[b->n++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == cast(unsigned char, token)); + return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : + luaO_pushfstring(ls->L, "%c", token); + } + else + return luaX_tokens[token-FIRST_RESERVED]; +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: + return luaX_token2str(ls, token); + } +} + + +void luaX_lexerror (LexState *ls, const char *msg, int token) { + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + luaX_lexerror(ls, msg, ls->t.token); +} + + +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); + TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ + if (ttisnil(o)) { + setbvalue(o, 1); /* make sure `str' will not be collected */ + luaC_checkGC(L); + } + return ts; +} + + +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + luaX_syntaxerror(ls, "chunk has too many lines"); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { + ls->decpoint = '.'; + ls->L = L; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ + next(ls); /* read first char */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (!strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +static void buffreplace (LexState *ls, char from, char to) { + size_t n = luaZ_bufflen(ls->buff); + char *p = luaZ_buffer(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + + +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + struct lconv *cv = localeconv(); + char old = ls->decpoint; + ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); + } while (isdigit(ls->current) || ls->current == '.'); + if (check_next(ls, "Ee")) /* `E'? */ + check_next(ls, "+-"); /* optional exponent sign */ + while (isalnum(ls->current) || ls->current == '_') + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int cont = 0; + (void)(cont); /* avoid warnings when `cont' is not used */ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ +#if defined(LUA_COMPAT_LSTR) + case '[': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `[' */ + cont++; +#if LUA_COMPAT_LSTR == 1 + if (sep == 0) + luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); +#endif + } + break; + } +#endif + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ +#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 + cont--; + if (sep == 0 && cont >= 0) break; +#endif + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); + while (ls->current != del) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, "unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + luaX_lexerror(ls, "unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\n': /* go through */ + case '\r': save(ls, '\n'); inclinenumber(ls); continue; + case EOZ: continue; /* will raise an error next loop */ + default: { + if (!isdigit(ls->current)) + save_and_next(ls); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10*c + (ls->current-'0'); + next(ls); + } while (++i<3 && isdigit(ls->current)); + if (c > UCHAR_MAX) + luaX_lexerror(ls, "escape sequence too large", TK_STRING); + save(ls, c); + } + continue; + } + } + save(ls, c); + next(ls); + continue; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': + case '\r': { + inclinenumber(ls); + continue; + } + case '-': { + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* long comment */ + luaZ_resetbuffer(ls->buff); + continue; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); + continue; + } + case '[': { + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') return '='; + else { next(ls); return TK_EQ; } + } + case '<': { + next(ls); + if (ls->current != '=') return '<'; + else { next(ls); return TK_LE; } + } + case '>': { + next(ls); + if (ls->current != '=') return '>'; + else { next(ls); return TK_GE; } + } + case '~': { + next(ls); + if (ls->current != '=') return '~'; + else { next(ls); return TK_NE; } + } + case '"': + case '\'': { + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* ... */ + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(ls->current)) return '.'; + else { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(ls->current)) { + lua_assert(!currIsNewline(ls)); + next(ls); + continue; + } + else if (isdigit(ls->current)) { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ + TString *ts; + do { + save_and_next(ls); + } while (isalnum(ls->current) || ls->current == '_'); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + else { + seminfo->ts = ts; + return TK_NAME; + } + } + else { + int c = ls->current; + next(ls); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +void luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); +} + diff --git a/source/lua/llex.h b/source/lua/llex.h new file mode 100644 index 0000000..a9201ce --- /dev/null +++ b/source/lua/llex.h @@ -0,0 +1,81 @@ +/* +** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_NAME, TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +/* array with token `names' */ +LUAI_DATA const char *const luaX_tokens []; + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + char decpoint; /* locale decimal point */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC void luaX_lookahead (LexState *ls); +LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); +LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/source/lua/llimits.h b/source/lua/llimits.h new file mode 100644 index 0000000..ca8dcb7 --- /dev/null +++ b/source/lua/llimits.h @@ -0,0 +1,128 @@ +/* +** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +typedef LUAI_UINT32 lu_int32; + +typedef LUAI_UMEM lu_mem; + +typedef LUAI_MEM l_mem; + + + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((unsigned int)(lu_mem)(p)) + + + +/* type to ensure maximum alignment */ +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; + + +/* result of a `usual argument conversion' over lua_Number */ +typedef LUAI_UACNUMBER l_uacNumber; + + +/* internal assertions for in-house debugging */ +#ifdef lua_assert + +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(l,e) lua_assert(e) + +#else + +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define api_check luai_apicheck + +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef lu_int32 Instruction; + + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + + +/* minimum size for the string table (must be power of 2) */ +#ifndef MINSTRTABSIZE +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#ifndef LUA_MINBUFFER +#define LUA_MINBUFFER 32 +#endif + + +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#ifndef luai_threadyield +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) ((void)0) +#else +#define condhardstacktests(x) x +#endif + +#endif diff --git a/source/lua/lmathlib.c b/source/lua/lmathlib.c new file mode 100644 index 0000000..441fbf7 --- /dev/null +++ b/source/lua/lmathlib.c @@ -0,0 +1,263 @@ +/* +** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + double ip; + double fp = modf(luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan2", math_atan2}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cosh", math_cosh}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, HUGE_VAL); + lua_setfield(L, -2, "huge"); +#if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +#endif + return 1; +} + diff --git a/source/lua/lmem.c b/source/lua/lmem.c new file mode 100644 index 0000000..ae7d8c9 --- /dev/null +++ b/source/lua/lmem.c @@ -0,0 +1,86 @@ +/* +** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#define lmem_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** Lua ensures that (ptr == NULL) iff (osize == 0). +** +** * frealloc(ud, NULL, 0, x) creates a new block of size `x' +** +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL). +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, errormsg); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +void *luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); + return NULL; /* to avoid warnings */ +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + block = (*g->frealloc)(g->ud, block, osize, nsize); + if (block == NULL && nsize > 0) + luaD_throw(L, LUA_ERRMEM); + lua_assert((nsize == 0) == (block == NULL)); + g->totalbytes = (g->totalbytes - osize) + nsize; + return block; +} + diff --git a/source/lua/lmem.h b/source/lua/lmem.h new file mode 100644 index 0000000..7c2dcb3 --- /dev/null +++ b/source/lua/lmem.h @@ -0,0 +1,49 @@ +/* +** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +#define luaM_reallocv(L,b,on,n,e) \ + ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ + luaM_toobig(L)) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) + +#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + + +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_toobig (lua_State *L); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *errormsg); + +#endif + diff --git a/source/lua/loadlib.c b/source/lua/loadlib.c new file mode 100644 index 0000000..6158c53 --- /dev/null +++ b/source/lua/loadlib.c @@ -0,0 +1,666 @@ +/* +** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Darwin (Mac OS X), an +** implementation for Windows, and a stub for other systems. +*/ + + +#include +#include + + +#define loadlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +#define LIBPREFIX "LOADLIB: " + +#define POF LUA_POF +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_DL_DLOPEN) +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +static void ll_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + void *lib = dlopen(path, RTLD_NOW); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +#undef setprogdir + +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HINSTANCE)lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + HINSTANCE lib = LoadLibraryA(path); + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DYLD) +/* +** {====================================================================== +** Native Mac OS X / Darwin Implementation +** ======================================================================= +*/ + +#include + + +/* Mac appends a `_' before C function names */ +#undef POF +#define POF "_" LUA_POF + + +static void pusherror (lua_State *L) { + const char *err_str; + const char *err_file; + NSLinkEditErrors err; + int err_num; + NSLinkEditError(&err, &err_num, &err_file, &err_str); + lua_pushstring(L, err_str); +} + + +static const char *errorfromcode (NSObjectFileImageReturnCode ret) { + switch (ret) { + case NSObjectFileImageInappropriateFile: + return "file is not a bundle"; + case NSObjectFileImageArch: + return "library is for wrong CPU type"; + case NSObjectFileImageFormat: + return "bad format"; + case NSObjectFileImageAccess: + return "cannot access file"; + case NSObjectFileImageFailure: + default: + return "unable to load library"; + } +} + + +static void ll_unloadlib (void *lib) { + NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); +} + + +static void *ll_load (lua_State *L, const char *path) { + NSObjectFileImage img; + NSObjectFileImageReturnCode ret; + /* this would be a rare case, but prevents crashing if it happens */ + if(!_dyld_present()) { + lua_pushliteral(L, "dyld not present"); + return NULL; + } + ret = NSCreateObjectFileImageFromFile(path, &img); + if (ret == NSObjectFileImageSuccess) { + NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSDestroyObjectFileImage(img); + if (mod == NULL) pusherror(L); + return mod; + } + lua_pushstring(L, errorfromcode(ret)); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); + if (nss == NULL) { + lua_pushfstring(L, "symbol " LUA_QS " not found", sym); + return NULL; + } + return (lua_CFunction)NSAddressOfSymbol(nss); +} + +/* }====================================================== */ + + + +#else +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void ll_unloadlib (void *lib) { + (void)lib; /* to avoid warnings */ +} + + +static void *ll_load (lua_State *L, const char *path) { + (void)path; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)lib; (void)sym; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + + +static void **ll_register (lua_State *L, const char *path) { + void **plib; + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ + if (!lua_isnil(L, -1)) /* is there an entry? */ + plib = (void **)lua_touserdata(L, -1); + else { /* no entry yet; create one */ + lua_pop(L, 1); + plib = (void **)lua_newuserdata(L, sizeof(const void *)); + *plib = NULL; + luaL_getmetatable(L, "_LOADLIB"); + lua_setmetatable(L, -2); + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_pushvalue(L, -2); + lua_settable(L, LUA_REGISTRYINDEX); + } + return plib; +} + + +/* +** __gc tag method: calls library's `ll_unloadlib' function with the lib +** handle +*/ +static int gctm (lua_State *L) { + void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); + if (*lib) ll_unloadlib(*lib); + *lib = NULL; /* mark library as closed */ + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void **reg = ll_register(L, path); + if (*reg == NULL) *reg = ll_load(L, path); + if (*reg == NULL) + return ERRLIB; /* unable to load library */ + else { + lua_CFunction f = ll_sym(L, *reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); + return 0; /* return function */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATHSEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATHSEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname) { + const char *path; + name = luaL_gsub(L, name, ".", LUA_DIRSEP); + lua_getfield(L, LUA_ENVIRONINDEX, pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + lua_pushliteral(L, ""); /* error accumulator */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename; + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_remove(L, -2); /* remove file name */ + lua_concat(L, 2); /* add entry to possible error message */ + } + return NULL; /* not found */ +} + + +static void loaderror (lua_State *L, const char *filename) { + luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int loader_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path"); + if (filename == NULL) return 1; /* library not found in this path */ + if (luaL_loadfile(L, filename) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static const char *mkfuncname (lua_State *L, const char *modname) { + const char *funcname; + const char *mark = strchr(modname, *LUA_IGMARK); + if (mark) modname = mark + 1; + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); + funcname = lua_pushfstring(L, POF"%s", funcname); + lua_remove(L, -2); /* remove 'gsub' result */ + return funcname; +} + + +static int loader_C (lua_State *L) { + const char *funcname; + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath"); + if (filename == NULL) return 1; /* library not found in this path */ + funcname = mkfuncname(L, name); + if (ll_loadfunc(L, filename, funcname) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static int loader_Croot (lua_State *L) { + const char *funcname; + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath"); + if (filename == NULL) return 1; /* root not found */ + funcname = mkfuncname(L, name); + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { + if (stat != ERRFUNC) loaderror(L, filename); /* real error */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; /* function not found */ + } + return 1; +} + + +static int loader_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.preload") " must be a table"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static const int sentinel_ = 0; +#define sentinel ((void *)&sentinel_) + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + int i; + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); + if (lua_toboolean(L, -1)) { /* is it there? */ + if (lua_touserdata(L, -1) == sentinel) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } + /* else must load it; iterate over available loaders */ + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.loaders") " must be a table"); + lua_pushliteral(L, ""); /* error message accumulator */ + for (i=1; ; i++) { + lua_rawgeti(L, -2, i); /* get a loader */ + if (lua_isnil(L, -1)) + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -2)); + lua_pushstring(L, name); + lua_call(L, 1, 1); /* call it */ + if (lua_isfunction(L, -1)) /* did it find module? */ + break; /* module loaded successfully */ + else if (lua_isstring(L, -1)) /* loader returned error message? */ + lua_concat(L, 2); /* accumulate it */ + else + lua_pop(L, 1); + } + lua_pushlightuserdata(L, sentinel); + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ + lua_call(L, 1, 1); /* run loaded module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ + + +static void setfenv (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, LUA_QL("module") " not called from a Lua function"); + lua_pushvalue(L, -2); + lua_setfenv(L, -2); + lua_pop(L, 1); +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) + return luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ + } + /* check whether table already has a _NAME field */ + lua_getfield(L, -1, "_NAME"); + if (!lua_isnil(L, -1)) /* is table an initialized module? */ + lua_pop(L, 1); + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + setfenv(L); + dooptions(L, loaded - 1); + return 0; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + + +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + +static void setpath (lua_State *L, const char *fieldname, const char *envname, + const char *def) { + const char *path = getenv(envname); + if (path == NULL) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, + LUA_PATHSEP AUXMARK LUA_PATHSEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"seeall", ll_seeall}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { + {"module", ll_module}, + {"require", ll_require}, + {NULL, NULL} +}; + + +static const lua_CFunction loaders[] = + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; + + +LUALIB_API int luaopen_package (lua_State *L) { + int i; + /* create new type _LOADLIB */ + luaL_newmetatable(L, "_LOADLIB"); + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); + /* create `package' table */ + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); +#if defined(LUA_COMPAT_LOADLIB) + lua_getfield(L, -1, "loadlib"); + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); +#endif + lua_pushvalue(L, -1); + lua_replace(L, LUA_ENVIRONINDEX); + /* create `loaders' table */ + lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); + /* fill it with pre-defined loaders */ + for (i=0; loaders[i] != NULL; i++) { + lua_pushcfunction(L, loaders[i]); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" + LUA_EXECDIR "\n" LUA_IGMARK); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + lua_newtable(L); + lua_setfield(L, -2, "preload"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ + lua_pop(L, 1); + return 1; /* return 'package' table */ +} + diff --git a/source/lua/lobject.c b/source/lua/lobject.c new file mode 100644 index 0000000..4ff5073 --- /dev/null +++ b/source/lua/lobject.c @@ -0,0 +1,214 @@ +/* +** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include +#include + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 31; + if (e == 0) return x; + else return ((x & 7)+8) << (e - 1); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = -1; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; + +} + + +int luaO_rawequalObj (const TValue *t1, const TValue *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* conversion failed */ + if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ + *result = cast_num(strtoul(s, &endptr, 16)); + if (*endptr == '\0') return 1; /* most common case */ + while (isspace(cast(unsigned char, *endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s); + break; + } + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': { + setnvalue(L->top, cast_num(va_arg(argp, int))); + incr_top(L); + break; + } + case 'f': { + setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + incr_top(L); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff); + break; + } + case '%': { + pushstr(L, "%"); + break; + } + default: { + char buff[3]; + buff[0] = '%'; + buff[1] = *(e+1); + buff[2] = '\0'; + pushstr(L, buff); + break; + } + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + size_t l; + source++; /* skip the `@' */ + bufflen -= sizeof(" '...' "); + l = strlen(source); + strcpy(out, ""); + if (l > bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + size_t len = strcspn(source, "\n\r"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/source/lua/lobject.h b/source/lua/lobject.h new file mode 100644 index 0000000..f1e447e --- /dev/null +++ b/source/lua/lobject.h @@ -0,0 +1,381 @@ +/* +** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define LAST_TAG LUA_TTHREAD + +#define NUM_TAGS (LAST_TAG+1) + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Tagged Values +*/ + +#define TValuefields Value value; int tt + +typedef struct lua_TValue { + TValuefields; +} TValue; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + +#define checkliveness(g,obj) \ + lua_assert(!iscollectable(obj) || \ + ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) + + +/* Macros to set values */ +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +#define setnvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + +#define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + +#define setbvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + +#define setsvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ + checkliveness(G(L),i_o); } + +#define setuvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ + checkliveness(G(L),i_o); } + +#define setthvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ + checkliveness(G(L),i_o); } + +#define setclvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ + checkliveness(G(L),i_o); } + +#define sethvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ + checkliveness(G(L),i_o); } + +#define setptvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + + + + +#define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ + checkliveness(G(L),o1); } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TValue *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + unsigned int hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(rawtsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TValue *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +/* masks for new-style vararg */ +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TValue *v; /* points to stack or to its own value */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + struct Node *next; /* for chaining */ + } nk; + TValue tvk; +} TKey; + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + +#define luaO_nilobject (&luaO_nilobject_) + +LUAI_DATA const TValue luaO_nilobject_; + +#define ceillog2(x) (luaO_log2((x)-1) + 1) + +LUAI_FUNC int luaO_log2 (unsigned int x); +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/source/lua/lopcodes.c b/source/lua/lopcodes.c new file mode 100644 index 0000000..4cc7452 --- /dev/null +++ b/source/lua/lopcodes.c @@ -0,0 +1,102 @@ +/* +** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORLOOP", + "SETLIST", + "CLOSE", + "CLOSURE", + "VARARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ +}; + diff --git a/source/lua/lopcodes.h b/source/lua/lopcodes.h new file mode 100644 index 0000000..41224d6 --- /dev/null +++ b/source/lua/lopcodes.h @@ -0,0 +1,268 @@ +/* +** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + +OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_VARARG) + 1) + + + +/*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (*) In OP_VARARG, if (B == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to `top' + + (*) In OP_SETLIST, if (B == 0) then B = `top'; + if (C == 0) then next `instruction' is real C + + (*) For comparisons, A specifies what condition the test should accept + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties. The format is: +** bits 0-1: op mode +** bits 2-3: C arg mode +** bits 4-5: B arg mode +** bit 6: instruction set register A +** bit 7: operator is a test +*/ + +enum OpArgMask { + OpArgN, /* argument is not used */ + OpArgU, /* argument is used */ + OpArgR, /* argument is a register or a jump offset */ + OpArgK /* argument is a constant or register/constant */ +}; + +LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/source/lua/loslib.c b/source/lua/loslib.c new file mode 100644 index 0000000..da06a57 --- /dev/null +++ b/source/lua/loslib.c @@ -0,0 +1,243 @@ +/* +** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define loslib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int os_pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static int os_execute (lua_State *L) { + lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + return 1; +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return os_pushresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return os_pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_getfield(L, -1, key); + if (lua_isnumber(L, -1)) + res = (int)lua_tointeger(L, -1); + else { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm *stm; + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[3]; + luaL_Buffer b; + cc[0] = '%'; cc[2] = '\0'; + luaL_buffinit(L, &b); + for (; *s; s++) { + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ + luaL_addchar(&b, *s); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + cc[1] = *(++s); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); +} + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_os (lua_State *L) { + luaL_register(L, LUA_OSLIBNAME, syslib); + return 1; +} + diff --git a/source/lua/lparser.c b/source/lua/lparser.c new file mode 100644 index 0000000..dda7488 --- /dev/null +++ b/source/lua/lparser.c @@ -0,0 +1,1339 @@ +/* +** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + +#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + lu_byte nactvar; /* # active locals outside the breakable structure */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); +} + + +static void errorlimit (FuncState *fs, int limit, const char *what) { + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", + fs->f->linedefined, limit, what); + luaX_lexerror(fs->ls, msg, 0); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + LUA_QS " expected (to close " LUA_QS " at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.s.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "too many local variables"); + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +#define new_localvarliteral(ls,v,n) \ + new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + for (i=0; inups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { + lua_assert(f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, + TString *, MAX_INT, ""); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; + luaC_objbarrier(fs->L, f, name); + lua_assert(v->k == VLOCAL || v->k == VUPVAL); + fs->upvalues[f->nups].k = cast_byte(v->k); + fs->upvalues[f->nups].info = cast_byte(v->u.s.info); + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) { /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + return VGLOBAL; + } + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found at current level; try upper one */ + if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) + return VGLOBAL; + var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ + var->k = VUPVAL; /* upvalue in this level */ + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void enterlevel (LexState *ls) { + if (++ls->L->nCcalls > LUAI_MAXCCALLS) + luaX_lexerror(ls, "chunk has too many syntax levels", 0); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + /* a block either controls scope or breaks (never both) */ + lua_assert(!bl->isbreakable || !bl->upval); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizep; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; + luaC_objbarrier(ls->L, f, func->f); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; if->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; + Proto *f = luaF_newproto(L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = -1; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + setptvalue2s(L, L->top, f); + incr_top(L); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_ret(fs, 0, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); + L->top -= 2; /* remove table and prototype from the stack */ +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + luaX_setinput(L, &lexstate, z, luaS_new(L, name)); + open_func(&lexstate, &funcstate); + funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ + luaX_next(&lexstate); /* read first token */ + chunk(&lexstate); + check(&lexstate, TK_EOS); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.fs == NULL); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + luaX_lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls), nparams++); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); +#if defined(LUA_COMPAT_VARARG) + /* use `arg' as default name */ + new_localvarliteral(ls, "arg", nparams++); + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->linedefined = line; + checknext(ls, '('); + if (needself) { + new_localvarliteral(ls, "self", 0); + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + chunk(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.s.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | + constructor | FUNCTION body | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + primaryexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality and inequality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, + "variables in assignment"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + checknext(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + chunk(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)", 0); + new_localvarliteral(ls, "(for limit)", 1); + new_localvarliteral(ls, "(for step)", 2); + new_localvar(ls, varname, 3); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)", nvars++); + new_localvarliteral(ls, "(for state)", nvars++); + new_localvarliteral(ls, "(for control)", nvars++); + /* create declared variables */ + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + + +static int test_then_block (LexState *ls) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + int condexit; + luaX_next(ls); /* skip IF or ELSEIF */ + condexit = cond(ls); + checknext(ls, TK_THEN); + block(ls); /* `then' part */ + return condexit; +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int flist; + int escapelist = NO_JUMP; + flist = test_then_block(ls); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + flist = test_then_block(ls); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, flist); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v); + while (ls->t.token == '.') + field(ls, v); + if (ls->t.token == ':') { + needself = 1; + field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) /* stat -> func */ + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + luaX_next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + luaX_next(ls); /* skip BREAK */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/source/lua/lparser.h b/source/lua/lparser.h new file mode 100644 index 0000000..18836af --- /dev/null +++ b/source/lua/lparser.h @@ -0,0 +1,82 @@ +/* +** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + +typedef struct expdesc { + expkind k; + union { + struct { int info, aux; } s; + lua_Number nval; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +typedef struct upvaldesc { + lu_byte k; + lu_byte info; +} upvaldesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + short nlocvars; /* number of elements in `locvars' */ + lu_byte nactvar; /* number of active local variables */ + upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ + unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ +} FuncState; + + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + const char *name); + + +#endif diff --git a/source/lua/lstate.c b/source/lua/lstate.c new file mode 100644 index 0000000..4313b83 --- /dev/null +++ b/source/lua/lstate.c @@ -0,0 +1,214 @@ +/* +** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) +#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) +#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + lua_State l; + global_State g; +} LG; + + + +static void stack_init (lua_State *L1, lua_State *L) { + /* initialize CallInfo array */ + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci - 1; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + /* initialize first ci */ + L1->ci->func = L1->top; + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TValue); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ + sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*g->totalbytes; +} + + +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = L->baseCcalls = 0; + L->status = 0; + L->base_ci = L->ci = NULL; + L->savedpc = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeall(L); /* collect all objects */ + lua_assert(g->rootgc == obj2gco(L)); + lua_assert(g->strt.nuse == 0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); + luaZ_freebuffer(L, &g->buff); + freestack(L, L); + lua_assert(g->totalbytes == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); + luaC_link(L, obj2gco(L1), LUA_TTHREAD); + preinit_state(L1, G(L)); + stack_init(L1, L); /* init stack */ + setobj2n(L, gt(L1), gt(L)); /* share table of globals */ + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + lua_assert(iswhite(obj2gco(L1))); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L1); + freestack(L, L1); + luaM_freemem(L, fromstate(L1), state_size(lua_State)); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + void *l = (*f)(ud, NULL, 0, state_size(LG)); + if (l == NULL) return NULL; + L = tostate(l); + g = &((LG *)L)->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->gcstate = GCSpause; + g->rootgc = obj2gco(L); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->tmudata = NULL; + g->totalbytes = sizeof(LG); + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + g->gcdept = 0; + for (i=0; imt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + else + luai_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = L->baseCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + luai_userstateclose(L); + close_state(L); +} + diff --git a/source/lua/lstate.h b/source/lua/lstate.h new file mode 100644 index 0000000..3bc575b --- /dev/null +++ b/source/lua/lstate.h @@ -0,0 +1,169 @@ +/* +** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* table of globals */ +#define gt(L) (&L->l_gt) + +/* registry */ +#define registry(L) (&G(L)->l_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for this function */ + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + const Instruction *savedpc; + int nresults; /* expected number of results from this function */ + int tailcalls; /* number of tail calls lost under this entry */ +} CallInfo; + + + +#define curr_func(L) (clvalue(L->ci->func)) +#define ci_func(ci) (clvalue((ci)->func)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *rootgc; /* list of all collectable objects */ + GCObject **sweepgc; /* position of sweep in `rootgc' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of weak tables (to be cleared) */ + GCObject *tmudata; /* last element of list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem totalbytes; /* number of bytes currently allocated */ + lu_mem estimate; /* an estimate of number of bytes actually in use */ + lu_mem gcdept; /* how much GC is `behind schedule' */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + TValue l_registry; + struct lua_State *mainthread; + UpVal uvhead; /* head of double-linked list of all open upvalues */ + struct Table *mt[NUM_TAGS]; /* metatables for basic types */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *savedpc; /* `savedpc' of current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + int stacksize; + int size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + unsigned short baseCcalls; /* nested C calls when resuming coroutine */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + TValue l_gt; /* table of globals */ + TValue env; /* temporary place for environments */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any Lua object into a GCObject */ +#define obj2gco(v) (cast(GCObject *, (v))) + + +LUAI_FUNC lua_State *luaE_newthread (lua_State *L); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/source/lua/lstring.c b/source/lua/lstring.c new file mode 100644 index 0000000..4911315 --- /dev/null +++ b/source/lua/lstring.c @@ -0,0 +1,111 @@ +/* +** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c +#define LUA_CORE + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash; + stringtable *tb; + int i; + if (G(L)->gcstate == GCSsweepstring) + return; /* cannot resize during GC traverse */ + newhash = luaM_newvector(L, newsize, GCObject *); + tb = &G(L)->strt; + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + unsigned int h = gco2ts(p)->hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast_int(h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + TString *ts; + stringtable *tb; + if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = luaC_white(G(L)); + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = obj2gco(ts); + tb->nuse++; + if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + unsigned int h = cast(unsigned int, l); /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + /* string may be dead */ + if (isdead(G(L), o)) changewhite(o); + return ts; + } + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); + u->uv.marked = luaC_white(G(L)); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + /* chain it on udata list (after main thread) */ + u->uv.next = G(L)->mainthread->next; + G(L)->mainthread->next = obj2gco(u); + return u; +} + diff --git a/source/lua/lstring.h b/source/lua/lstring.h new file mode 100644 index 0000000..73a2ff8 --- /dev/null +++ b/source/lua/lstring.h @@ -0,0 +1,31 @@ +/* +** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) + +#define sizeudata(u) (sizeof(union Udata)+(u)->len) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/source/lua/lstrlib.c b/source/lua/lstrlib.c new file mode 100644 index 0000000..7a03489 --- /dev/null +++ b/source/lua/lstrlib.c @@ -0,0 +1,871 @@ +/* +** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, l); + return 1; +} + + +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + if (pos < 0) pos += (ptrdiff_t)len + 1; + return (pos >= 0) ? pos : 0; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); + ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + while (l--) luaL_addchar(&b, s[l]); + luaL_pushresult(&b); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case L_ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = classend(ms, p); /* points to what is next */ + int m = ssrc_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index"); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushinteger(L, s2-s+1); + lua_pushinteger(L, s2-s+l2); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { + MatchState ms; + size_t ls; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tostring(L, lua_upvalueindex(2)); + const char *src; + ms.L = L; + ms.src_init = s; + ms.src_end = s+ls; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + if ((e = match(&ms, src, p)) != NULL) { + lua_Integer newstart = e-s; + if (e == src) newstart++; /* empty match? go at least one position */ + lua_pushinteger(L, newstart); + lua_replace(L, lua_upvalueindex(3)); + return push_captures(&ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + luaL_checkstring(L, 1); + luaL_checkstring(L, 2); + lua_settop(L, 2); + lua_pushinteger(L, 0); + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + const char *news = lua_tolstring(ms->L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) + luaL_addchar(b, news[i]); + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + lua_State *L = ms->L; + switch (lua_type(L, 3)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + add_s(ms, b, s, e); + return; + } + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checkstring(L, 2); + int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_addchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + + +static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_addchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + break; + } + case '\r': { + luaL_addlstring(b, "\\r", 2); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_addchar(b, *s); + break; + } + } + s++; + } + luaL_addchar(b, '"'); +} + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, &b, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gfind", gfind_nodef}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); /* set string metatable */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* string library... */ + lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif + createmetatable(L); + return 1; +} + diff --git a/source/lua/ltable.c b/source/lua/ltable.c new file mode 100644 index 0000000..ec84f4f --- /dev/null +++ b/source/lua/ltable.c @@ -0,0 +1,588 @@ +/* +** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include +#include + +#define ltable_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT > 26 +#define MAXBITS 26 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast_int(sizeof(lua_Number)/sizeof(int)) + + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_TNIL}, /* value */ + {{{NULL}, LUA_TNIL, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + if (luai_numeq(n, 0)) /* avoid problems with -0 */ + return gnode(t, 0); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, a[0]); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TValue *key) { + if (ttisnumber(key)) { + lua_Number n = nvalue(key); + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signalled by -1. +*/ +static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaO_rawequalObj(key2tval(n), key) || + (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && + gcvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } + else n = gnext(n); + } while (n); + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + return 0; /* to avoid warnings */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast_num(i+1)); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, key2tval(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static int computesizes (int nums[], int *narray) { + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ + } + } + if (a == *narray) break; /* all elements already counted */ + } + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(key2tval(n), nums); + totaluse++; + } + } + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common `dummynode' */ + lsize = 0; + } + else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i=0; ilsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); + } + if (nold != dummynode) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = (t->node == dummynode) ? 0 : sizenode(t); + resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int nhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, obj2gco(t), LUA_TTABLE); + t->metatable = NULL; + t->flags = cast_byte(~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = cast(Node *, dummynode); + setarrayvector(L, t, narray); + setnodevector(L, t, nhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->node != dummynode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TValue); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree-- > t->node) { + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TValue *newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || mp == dummynode) { + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + return luaH_set(L, t, key); /* re-insert key into grown table */ + } + lua_assert(n != dummynode); + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; + luaC_barriert(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getnum (Table *t, int key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { + lua_Number nk = cast_num(key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(key2tval(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + t->flags = 0; + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(nvalue(key))) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TValue *luaH_setnum (lua_State *L, Table *t, int key) { + const TValue *p = luaH_getnum(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + return newkey(L, t, &k); + } +} + + +TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { + const TValue *p = luaH_getstr(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setsvalue(L, &k, key); + return newkey(L, t, &k); + } +} + + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getnum(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getnum(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getnum(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (t->node == dummynode) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (Node *n) { return n == dummynode; } + +#endif diff --git a/source/lua/ltable.h b/source/lua/ltable.h new file mode 100644 index 0000000..f5b9d5e --- /dev/null +++ b/source/lua/ltable.h @@ -0,0 +1,40 @@ +/* +** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.nk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define key2tval(n) (&(n)->i_key.tvk) + + +LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC int luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (Node *n); +#endif + + +#endif diff --git a/source/lua/ltablib.c b/source/lua/ltablib.c new file mode 100644 index 0000000..b6d9cb4 --- /dev/null +++ b/source/lua/ltablib.c @@ -0,0 +1,287 @@ +/* +** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i <= n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushinteger(L, i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } + return 0; +} + + +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} + + +static int getn (lua_State *L) { + lua_pushinteger(L, aux_getn(L, 1)); + return 1; +} + + +static int setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); +#ifndef luaL_setn + luaL_setn(L, 1, luaL_checkint(L, 2)); +#else + luaL_error(L, LUA_QL("setn") " is obsolete"); +#endif + lua_pushvalue(L, 1); + return 1; +} + + +static int tinsert (lua_State *L) { + int e = aux_getn(L, 1) + 1; /* first empty element */ + int pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + int i; + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > e) e = pos; /* `grow' array if necessary */ + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + } + } + luaL_setn(L, 1, e); /* new size */ + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int e = aux_getn(L, 1); + int pos = luaL_optint(L, 2, e); + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ + return 0; /* nothing to remove */ + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", + "proto", "upval" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__len", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttype(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/source/lua/ltm.h b/source/lua/ltm.h new file mode 100644 index 0000000..64343b7 --- /dev/null +++ b/source/lua/ltm.h @@ -0,0 +1,54 @@ +/* +** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + TM_LEN, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +LUAI_DATA const char *const luaT_typenames[]; + + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +#endif diff --git a/source/lua/lua.h b/source/lua/lua.h new file mode 100644 index 0000000..a4b73e7 --- /dev/null +++ b/source/lua/lua.h @@ -0,0 +1,388 @@ +/* +** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.5" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status; 0 is OK */ +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/source/lua/luaconf.h b/source/lua/luaconf.h new file mode 100644 index 0000000..e2cb261 --- /dev/null +++ b/source/lua/luaconf.h @@ -0,0 +1,763 @@ +/* +** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) +#define LUA_WIN +#endif + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_DL_DYLD /* does not need extra library */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +#else +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_PATH_DEFAULT \ + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +#define LUA_CPATH_DEFAULT \ + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" +#endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER ptrdiff_t + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) + +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif + +#else + +#define LUA_API extern + +#endif + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +#if defined(luaall_c) +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ + +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC + +#else +#define LUAI_FUNC extern +#define LUAI_DATA extern +#endif + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +#if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +#if defined(LUA_USE_ISATTY) +#include +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +#define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +#if defined(LUA_USE_READLINE) +#include +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) +#else +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } +#endif + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +#undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +#undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +#define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +#define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +#define LUA_COMPAT_LSTR 1 + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,o) { (void)L; assert(o); } +#else +#define luai_apicheck(L,o) { (void)L; } +#endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else +/* 16-bit ints */ +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +#define LUAI_MAXCALLS 20000 + + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. (must be smaller than +** -LUA_REGISTRYINDEX) +*/ +#define LUAI_MAXCSTACK 8000 + + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +#define LUAI_MAXCCALLS 200 + + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXVARS 200 + + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXUPVALUES 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define lua_str2number(s,p) strtod((s), (p)) + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +#if defined(_MSC_VER) + +#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +#else + +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +#define lua_number2integer(i,n) lua_number2int(i, n) + +#endif + + +/* this option always works, but may be slow */ +#else +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +#if defined(__cplusplus) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +#define LUA_MAXCAPTURES 32 + + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +#if defined(loslib_c) || defined(luaall_c) + +#if defined(LUA_USE_MKSTEMP) +#include +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#endif + +#endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if defined(LUA_USE_POPEN) + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +#elif defined(LUA_WIN) + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +#else + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) + +#endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +#if defined(LUA_USE_DLOPEN) +#define LUA_DL_DLOPEN +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +#define LUAI_EXTRASPACE 0 + + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +#if defined(LUA_USELONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/source/lua/lualib.h b/source/lua/lualib.h new file mode 100644 index 0000000..469417f --- /dev/null +++ b/source/lua/lualib.h @@ -0,0 +1,53 @@ +/* +** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* Key to file-handle type */ +#define LUA_FILEHANDLE "FILE*" + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int (luaopen_base) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int (luaopen_string) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUALIB_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/source/lua/lundump.c b/source/lua/lundump.c new file mode 100644 index 0000000..8010a45 --- /dev/null +++ b/source/lua/lundump.c @@ -0,0 +1,227 @@ +/* +** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define lundump_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + const char* name; +} LoadState; + +#ifdef LUAC_TRUST_BINARIES +#define IF(c,s) +#define error(S,s) +#else +#define IF(c,s) if (c) error(S,s) + +static void error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} +#endif + +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + size_t r=luaZ_read(S->Z,b,size); + IF (r!=0, "unexpected end"); +} + +static int LoadChar(LoadState* S) +{ + char x; + LoadVar(S,x); + return x; +} + +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S,x); + IF (x<0, "bad integer"); + return x; +} + +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S,x); + return x; +} + +static TString* LoadString(LoadState* S) +{ + size_t size; + LoadVar(S,size); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + LoadBlock(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode(LoadState* S, Proto* f) +{ + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); +} + +static Proto* LoadFunction(LoadState* S, TString* p); + +static void LoadConstants(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TValue); + f->sizek=n; + for (i=0; ik[i]); + for (i=0; ik[i]; + int t=LoadChar(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o,LoadChar(S)!=0); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: + error(S,"bad constant"); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=NULL; + for (i=0; ip[i]=LoadFunction(S,f->source); +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=NULL; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; iupvalues[i]=NULL; + for (i=0; iupvalues[i]=LoadString(S); +} + +static Proto* LoadFunction(LoadState* S, TString* p) +{ + Proto* f; + if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); + f=luaF_newproto(S->L); + setptvalue2s(S->L,S->L->top,f); incr_top(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadDebug(S,f); + IF (!luaG_checkcode(f), "bad code"); + S->L->top--; + S->L->nCcalls--; + return f; +} + +static void LoadHeader(LoadState* S) +{ + char h[LUAC_HEADERSIZE]; + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + if (*name=='@' || *name=='=') + S.name=name+1; + else if (*name==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=name; + S.L=L; + S.Z=Z; + S.b=buff; + LoadHeader(&S); + return LoadFunction(&S,luaS_newliteral(L,"=?")); +} + +/* +* make header +*/ +void luaU_header (char* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); + h+=sizeof(LUA_SIGNATURE)-1; + *h++=(char)LUAC_VERSION; + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ +} diff --git a/source/lua/lundump.h b/source/lua/lundump.h new file mode 100644 index 0000000..c80189d --- /dev/null +++ b/source/lua/lundump.h @@ -0,0 +1,36 @@ +/* +** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (char* h); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + +#ifdef luac_c +/* print one chunk; from print.c */ +LUAI_FUNC void luaU_print (const Proto* f, int full); +#endif + +/* for header of binary files -- this is Lua 5.1 */ +#define LUAC_VERSION 0x51 + +/* for header of binary files -- this is the official format */ +#define LUAC_FORMAT 0 + +/* size of header of binary files */ +#define LUAC_HEADERSIZE 12 + +#endif diff --git a/source/lua/lvm.c b/source/lua/lvm.c new file mode 100644 index 0000000..e0a0cd8 --- /dev/null +++ b/source/lua/lvm.c @@ -0,0 +1,767 @@ +/* +** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define lvm_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; + lua_Number n = nvalue(obj); + lua_number2str(s, n); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L, const Instruction *pc) { + lu_byte mask = L->hookmask; + const Instruction *oldpc = L->savedpc; + L->savedpc = pc; + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + } + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(L->ci)->l.p; + int npc = pcRel(pc, p); + int newline = getline(p, npc); + /* call linehook when enter a new function, when jump back (loop), + or when enter a new line */ + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) + luaD_callhook(L, LUA_HOOKLINE, newline); + } +} + + +static void callTMres (lua_State *L, StkId res, const TValue *f, + const TValue *p1, const TValue *p2) { + ptrdiff_t result = savestack(L, res); + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); + L->top += 3; + luaD_call(L, L->top - 3, 1); + res = restorestack(L, result); + L->top--; + setobjs2s(L, res, L->top); +} + + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3) { + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + setobj2s(L, L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, val, tm, t, key); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in gettable"); +} + + +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + TValue temp; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(L, oldval, val); + h->flags = 0; + luaC_barriert(L, h, val); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + /* else repeat with `tm' */ + setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ + t = &temp; + } + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + callTMres(L, res, tm, p1, p2); + return 1; +} + + +static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TValue *tm1 = fasttm(L, mt1, event); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + const TValue *tm1 = luaT_gettmbyobj(L, p1, event); + const TValue *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, L->top, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numlt(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numle(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, L->top, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ + (void)tostring(L, top - 2); /* result is first op (as string) */ + else { + /* at least two string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (n = 1; n < total && tostring(L, top-n-1); n++) { + size_t l = tsvalue(top-n-1)->len; + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number nb = nvalue(b), nc = nvalue(c); + switch (op) { + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; + case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) break; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) + + +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} + + +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +#define arith_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(nb, nc)); \ + } \ + else \ + Protect(Arith(L, ra, rb, rc, tm)); \ + } + + + +void luaV_execute (lua_State *L, int nexeccalls) { + LClosure *cl; + StkId base; + TValue *k; + const Instruction *pc; + reentry: /* entry point */ + lua_assert(isLua(L->ci)); + pc = L->savedpc; + cl = &clvalue(L->ci->func)->l; + base = L->base; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L, pc); + if (L->status == LUA_YIELD) { /* did hook yield? */ + L->savedpc = pc - 1; + return; + } + base = L->base; + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(L, ra, RB(i)); + continue; + } + case OP_LOADK: { + setobj2s(L, ra, KBx(i)); + continue; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + continue; + } + case OP_LOADNIL: { + TValue *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + continue; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + continue; + } + case OP_GETGLOBAL: { + TValue g; + TValue *rb = KBx(i); + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(rb)); + Protect(luaV_gettable(L, &g, rb, ra)); + continue; + } + case OP_GETTABLE: { + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + continue; + } + case OP_SETGLOBAL: { + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + Protect(luaV_settable(L, &g, KBx(i), ra)); + continue; + } + case OP_SETUPVAL: { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + continue; + } + case OP_SETTABLE: { + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + continue; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Protect(luaC_checkGC(L)); + continue; + } + case OP_SELF: { + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + continue; + } + case OP_ADD: { + arith_op(luai_numadd, TM_ADD); + continue; + } + case OP_SUB: { + arith_op(luai_numsub, TM_SUB); + continue; + } + case OP_MUL: { + arith_op(luai_nummul, TM_MUL); + continue; + } + case OP_DIV: { + arith_op(luai_numdiv, TM_DIV); + continue; + } + case OP_MOD: { + arith_op(luai_nummod, TM_MOD); + continue; + } + case OP_POW: { + arith_op(luai_numpow, TM_POW); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(nb)); + } + else { + Protect(Arith(L, ra, rb, rb, TM_UNM)); + } + continue; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + continue; + } + case OP_LEN: { + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { + setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); + break; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + break; + } + default: { /* try metamethod */ + Protect( + if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) + luaG_typeerror(L, rb, "get length of"); + ) + } + } + continue; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + setobjs2s(L, RA(i), base+b); + continue; + } + case OP_JMP: { + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_EQ: { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (equalobj(L, rb, rc) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LT: { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LE: { + Protect( + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_TEST: { + if (l_isfalse(ra) != GETARG_C(i)) + dojump(L, pc, GETARG_sBx(*pc)); + pc++; + continue; + } + case OP_TESTSET: { + TValue *rb = RB(i); + if (l_isfalse(rb) != GETARG_C(i)) { + setobjs2s(L, ra, rb); + dojump(L, pc, GETARG_sBx(*pc)); + } + pc++; + continue; + } + case OP_CALL: { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + switch (luaD_precall(L, ra, nresults)) { + case PCRLUA: { + nexeccalls++; + goto reentry; /* restart luaV_execute over new Lua function */ + } + case PCRC: { + /* it was a C function (`precall' called it); adjust results */ + if (nresults >= 0) L->top = L->ci->top; + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_TAILCALL: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + switch (luaD_precall(L, ra, LUA_MULTRET)) { + case PCRLUA: { + /* tail call: put new frame in place of previous one */ + CallInfo *ci = L->ci - 1; /* previous frame */ + int aux; + StkId func = ci->func; + StkId pfunc = (ci+1)->func; /* previous function index */ + if (L->openupval) luaF_close(L, ci->base); + L->base = ci->base = ci->func + ((ci+1)->base - pfunc); + for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ + setobjs2s(L, func+aux, pfunc+aux); + ci->top = L->top = func+aux; /* correct top */ + lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); + ci->savedpc = L->savedpc; + ci->tailcalls++; /* one more call lost */ + L->ci--; /* remove new frame */ + goto reentry; + } + case PCRC: { /* it was a C function (`precall' called it) */ + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_RETURN: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (L->openupval) luaF_close(L, base); + L->savedpc = pc; + b = luaD_poscall(L, ra); + if (--nexeccalls == 0) /* was previous function running `here'? */ + return; /* no: return */ + else { /* yes: continue its execution */ + if (b) L->top = L->ci->top; + lua_assert(isLua(L->ci)); + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); + goto reentry; + } + } + case OP_FORLOOP: { + lua_Number step = nvalue(ra+2); + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number limit = nvalue(ra+1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + dojump(L, pc, GETARG_sBx(i)); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + continue; + } + case OP_FORPREP: { + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_TFORLOOP: { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb+3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = L->ci->top; + cb = RA(i) + 3; /* previous call may change the stack */ + if (!ttisnil(cb)) { /* continue loop? */ + setobjs2s(L, cb-1, cb); /* save control variable */ + dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ + } + pc++; + continue; + } + case OP_SETLIST: { + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; + Table *h; + if (n == 0) { + n = cast_int(L->top - ra) - 1; + L->top = L->ci->top; + } + if (c == 0) c = cast_int(*pc++); + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + setobj2t(L, luaH_setnum(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; + } + case OP_CLOSE: { + luaF_close(L, ra); + continue; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, cl->env); + ncl->l.p = p; + for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(L, ra, ncl); + Protect(luaC_checkGC(L)); + continue; + } + case OP_VARARG: { + int b = GETARG_B(i) - 1; + int j; + CallInfo *ci = L->ci; + int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; + if (b == LUA_MULTRET) { + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + b = n; + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, ci->base - n + j); + } + else { + setnilvalue(ra + j); + } + } + continue; + } + } + } +} + diff --git a/source/lua/lvm.h b/source/lua/lvm.h new file mode 100644 index 0000000..bfe4f56 --- /dev/null +++ b/source/lua/lvm.h @@ -0,0 +1,36 @@ +/* +** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); +LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); +LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/source/lua/lzio.c b/source/lua/lzio.c new file mode 100644 index 0000000..293edd5 --- /dev/null +++ b/source/lua/lzio.c @@ -0,0 +1,82 @@ +/* +** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c +#define LUA_CORE + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return EOZ; + else { + z->n++; /* luaZ_fill removed first byte; put back it */ + z->p--; + } + } + return char2int(*z->p); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (luaZ_lookahead(z) == EOZ) + return n; /* return number of missing bytes */ + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaZ_resizebuffer(L, buff, n); + } + return buff->buffer; +} + + diff --git a/source/lua/lzio.h b/source/lua/lzio.h new file mode 100644 index 0000000..51d695d --- /dev/null +++ b/source/lua/lzio.h @@ -0,0 +1,67 @@ +/* +** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC int luaZ_lookahead (ZIO *z); + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/source/luad/LICENSE.txt b/source/luad/LICENSE.txt new file mode 100644 index 0000000..93820af --- /dev/null +++ b/source/luad/LICENSE.txt @@ -0,0 +1,25 @@ +LuaD +http://github.com/JakobOvrum/LuaD +================================================================= + Copyright (c) 2010-2011 Jakob Ovrum + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/source/luad/all.d b/source/luad/all.d new file mode 100644 index 0000000..a92c9ae --- /dev/null +++ b/source/luad/all.d @@ -0,0 +1,10 @@ +/++ + Convenience module for importing the entire public LuaD API. + + This module does not import the C API bindings. ++/ +module luad.all; + +public import luad.base, luad.table, luad.lfunction, luad.dynamic, luad.state, luad.lmodule; + +public import luad.conversions.functions : LuaVariableReturn, variableReturn; diff --git a/source/luad/base.d b/source/luad/base.d new file mode 100644 index 0000000..8bc5ddb --- /dev/null +++ b/source/luad/base.d @@ -0,0 +1,224 @@ +module luad.base; + +import luad.c.all; +import luad.stack; + +import core.stdc.string : strlen; + +/** + * Enumerates all Lua types. + */ +enum LuaType +{ + ///string + String = LUA_TSTRING, + ///number + Number = LUA_TNUMBER, + //table + Table = LUA_TTABLE, + ///nil + Nil = LUA_TNIL, + ///boolean + Boolean = LUA_TBOOLEAN, + ///function + Function = LUA_TFUNCTION, + ///userdata + Userdata = LUA_TUSERDATA, + ///ditto + LightUserdata = LUA_TLIGHTUSERDATA, + ///thread + Thread = LUA_TTHREAD +} + +package struct Nil{} + +/** + * Special value representing the Lua type and value nil. + * Examples: + * Useful for clearing keys in a table: + * -------------------------- + lua["n"] = 1.23; + assert(lua.get!double("n") == 1.23); + + lua["n"] = nil; + assert(lua["n"].type == LuaType.Nil); + * -------------------------- + */ +public Nil nil; + +/** + * Represents a reference to a Lua value of any type. + * It contains only the bare minimum of functionality which all Lua values support. + * For a generic reference type with more functionality, see $(DPREF dynamic,LuaDynamic). + */ +struct LuaObject +{ + private: + int r = LUA_REFNIL; + lua_State* L = null; + + package: + this(lua_State* L, int idx) + { + this.L = L; + + lua_pushvalue(L, idx); + r = luaL_ref(L, LUA_REGISTRYINDEX); + } + + void push() nothrow + { + lua_rawgeti(L, LUA_REGISTRYINDEX, r); + } + + static void checkType(lua_State* L, int idx, int expectedType, const(char)* expectedName) + { + int t = lua_type(L, idx); + if(t != expectedType) + { + luaL_error(L, "attempt to create %s with %s", expectedName, lua_typename(L, t)); + } + } + + public: + @trusted this(this) + { + push(); + r = luaL_ref(L, LUA_REGISTRYINDEX); + } + + @trusted nothrow ~this() + { + luaL_unref(L, LUA_REGISTRYINDEX, r); + } + + /// The underlying $(D lua_State) pointer for interfacing with C. + lua_State* state() pure nothrow @safe @property + { + return L; + } + + /** + * Release this reference. + * + * This reference becomes a nil reference. + * This is only required when you want to _release the reference before the lifetime + * of this $(D LuaObject) has ended. + */ + void release() pure nothrow @safe + { + r = LUA_REFNIL; + L = null; + } + + /** + * Type of referenced object. + * See_Also: + * $(MREF LuaType) + */ + @property LuaType type() @trusted nothrow + { + push(); + auto result = cast(LuaType)lua_type(state, -1); + lua_pop(state, 1); + return result; + } + + /** + * Type name of referenced object. + */ + @property string typeName() @trusted /+ nothrow +/ + { + push(); + const(char)* cname = luaL_typename(state, -1); // TODO: Doesn't have to use luaL_typename, i.e. no copy + auto name = cname[0.. strlen(cname)].idup; + lua_pop(state, 1); + return name; + } + + /// Boolean whether or not the referenced object is nil. + @property bool isNil() pure nothrow @safe + { + return r == LUA_REFNIL; + } + + /** + * Convert the referenced object into a textual representation. + * + * The returned string is formatted in the same way the Lua $(D tostring) function formats. + * + * Returns: + * String representation of referenced object + */ + string toString() @trusted + { + push(); + + size_t len; + const(char)* cstr = luaL_tolstring(state, -1, &len); + auto str = cstr[0 .. len].idup; + + lua_pop(state, 2); + return str; + } + + /** + * Attempt _to convert the referenced object _to the specified D type. + * Examples: + ----------------------- + auto results = lua.doString(`return "hello!"`); + assert(results[0].to!string() == "hello!"); + ----------------------- + */ + T to(T)() + { + static void typeMismatch(lua_State* L, int t, int e) + { + luaL_error(L, "attempt to convert LuaObject with type %s to a %s", lua_typename(L, t), lua_typename(L, e)); + } + + push(); + return popValue!(T, typeMismatch)(state); + } + + /** + * Compare this object to another with Lua's equality semantics. + * Also returns false if the two objects are in different Lua states. + */ + bool opEquals(T : LuaObject)(ref T o) @trusted + { + if(o.state != this.state) + return false; + + push(); + o.push(); + scope(success) lua_pop(state, 2); + + return lua_equal(state, -1, -2); + } +} + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + + lua_pushstring(L, "foobar"); + auto o = popValue!LuaObject(L); + + assert(!o.isNil); + assert(o.type == LuaType.String); + assert(o.typeName == "string"); + assert(o.to!string() == "foobar"); + + lua_pushnil(L); + auto nilref = popValue!LuaObject(L); + + assert(nilref.isNil); + assert(nilref.typeName == "nil"); + + assert(o != nilref); + + auto o2 = o; + assert(o2 == o); +} diff --git a/source/luad/c/all.d b/source/luad/c/all.d new file mode 100644 index 0000000..c8ad520 --- /dev/null +++ b/source/luad/c/all.d @@ -0,0 +1,9 @@ +/++ +Convenience module to import the Lua 5.1 C API. +This module also exposes luaL_tolstring which works like the function with the same name in Lua 5.2. +See_Also: + Documentation for this API can be found $(LINK2 http://www.lua.org/manual/5.1/manual.html,here). ++/ +module luad.c.all; + +public import luad.c.lua, luad.c.lauxlib, luad.c.lualib, luad.c.tostring; \ No newline at end of file diff --git a/source/luad/c/lauxlib.d b/source/luad/c/lauxlib.d new file mode 100644 index 0000000..fe18677 --- /dev/null +++ b/source/luad/c/lauxlib.d @@ -0,0 +1,250 @@ +module luad.c.lauxlib; +import luad.c.luaconf; +/* +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +//C #ifndef lauxlib_h +//C #define lauxlib_h + + +//C #include +//import std.stddef; +//C #include +//import std.stdio; + +//C #include "lua.h" +import luad.c.lua; + +extern (C): + +//C #if defined(LUA_COMPAT_GETN) +//C LUALIB_API int (luaL_getn) (lua_State *L, int t); +//C LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +//C #else +//C #define luaL_getn(L,i) ((int)lua_objlen(L, i)) +//C #define luaL_setn(L,i,j) ((void)0) /* no op! */ +//C #endif +int luaL_getn(lua_State* L, int i) { return cast(int) lua_objlen(L, i); } + +void luaL_setn(lua_State* L, int i, int j) { } + +//C #if defined(LUA_COMPAT_OPENLIB) +//C #define luaI_openlib luaL_openlib +//C #endif +alias luaL_openlib luaI_openlib; + + +/* extra error code for `luaL_load' */ +//C #define LUA_ERRFILE (LUA_ERRERR+1) + + +//C typedef struct luaL_Reg { +//C const char *name; +//C lua_CFunction func; +//C } luaL_Reg; +struct luaL_Reg +{ + char* name; + lua_CFunction func; +} + + + +//C LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, +//C const luaL_Reg *l, int nup); +void luaL_openlib(lua_State *L, const(char)* libname, const luaL_Reg *l, int nup); +//C LUALIB_API void (luaL_register) (lua_State *L, const char *libname, +//C const luaL_Reg *l); +void luaL_register(lua_State *L, const(char)* libname, const luaL_Reg *l); +//C LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +int luaL_getmetafield(lua_State *L, int obj, const(char)* e); +//C LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +int luaL_callmeta(lua_State *L, int obj, const(char)* e); +//C LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +int luaL_typerror(lua_State *L, int narg, const(char)* tname); +//C LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +int luaL_argerror(lua_State *L, int numarg, const(char)* extramsg); +//C LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, +//C size_t *l); +const(char)* luaL_checklstring(lua_State *L, int numArg, size_t *l); +//C LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, +//C const char *def, size_t *l); +const(char)* luaL_optlstring(lua_State *L, int numArg, const(char)* def, size_t *l); +//C LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +lua_Number luaL_checknumber(lua_State *L, int numArg); +//C LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); +lua_Number luaL_optnumber(lua_State *L, int nArg, lua_Number def); + +//C LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +lua_Integer luaL_checkinteger(lua_State *L, int numArg); +//C LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, +//C lua_Integer def); +lua_Integer luaL_optinteger(lua_State *L, int nArg, lua_Integer def); + +//C LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +void luaL_checkstack(lua_State *L, int sz, const(char)* msg); +//C LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +void luaL_checktype(lua_State *L, int narg, int t); +//C LUALIB_API void (luaL_checkany) (lua_State *L, int narg); +void luaL_checkany(lua_State *L, int narg); + +//C LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +int luaL_newmetatable(lua_State *L, const(char)* tname); +//C LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); +void * luaL_checkudata(lua_State *L, int ud, const(char)* tname); + +//C LUALIB_API void (luaL_where) (lua_State *L, int lvl); +void luaL_where(lua_State *L, int lvl); +//C LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); +int luaL_error(lua_State *L, const(char)* fmt,...); + +//C LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, +//C const char *const lst[]); +int luaL_checkoption(lua_State *L, int narg, const(char)* def, const(char*)* lst); + +//C LUALIB_API int (luaL_ref) (lua_State *L, int t); +int luaL_ref(lua_State *L, int t); +//C LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); +void luaL_unref(lua_State *L, int t, int _ref) nothrow; + +//C LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); + int luaL_loadfile(lua_State *L, const(char)* filename); +//C LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, +//C const char *name); +int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name); +//C LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); +int luaL_loadstring(lua_State *L, const(char)* s); + +//C LUALIB_API lua_State *(luaL_newstate) (void); +lua_State * luaL_newstate(); + + +//C LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, +//C const char *r); +const(char)* luaL_gsub(lua_State *L, const(char)* s, const(char)* p, const(char)* r); + +//C LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, +//C const char *fname, int szhint); +const(char)* luaL_findtable(lua_State *L, int idx, const(char)* fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +//C #define luaL_argcheck(L, cond,numarg,extramsg) ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +void luaL_argcheck(lua_State* L, int cond, int numarg, const(char)* extramsg) { if (!cond) luaL_argerror(L, numarg, extramsg); } +//C #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +const(char)* luaL_checkstring(lua_State* L, int n) { return luaL_checklstring(L, n, null); } +//C #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +const(char)* luaL_optstring(lua_State* L, int n, const(char)* d) { return luaL_optlstring(L, n, d, null); } +//C #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +int luaL_checkint(lua_State* L, int n) { return cast(int) luaL_checkinteger(L, n); } +//C #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +int luaL_optint (lua_State* L, int n, int d) { return cast(int) luaL_optinteger(L, n, d); } +//C #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +long luaL_checklong(lua_State* L, int n) { return cast(long)luaL_checkinteger(L, n); } +//C #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) +long luaL_optlong(lua_State* L, int n, int d) { return cast(long)luaL_optinteger(L, n, d); } + +//C #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) +const(char)* luaL_typename(lua_State* L, int i) nothrow { return lua_typename(L, lua_type(L, i)); } + +//C #define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) +int luaL_dofile(lua_State* L, const(char)* fn) { return luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0); } + +//C #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) +int luaL_dostring(lua_State*L, const(char)* s) { return luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0); } + +//C #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) +void luaL_getmetatable(lua_State* L, const(char)* s) { lua_getfield(L, LUA_REGISTRYINDEX, s); } + +//C #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +bool luaL_opt(lua_State* L, int function(lua_State*, int) f, int n, int d) { return luaL_opt(L, f, n, d); } + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +//C typedef struct luaL_Buffer { +//C char *p; /* current position in buffer */ +//C int lvl; /* number of strings in the stack (level) */ +//C lua_State *L; +//C char buffer[LUAL_BUFFERSIZE]; +//C } luaL_Buffer; +struct luaL_Buffer +{ + char *p; + int lvl; + lua_State *L; + char [LUAL_BUFFERSIZE]buffer; +} +//C #define luaL_addchar(B,c) ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), (*(B)->p++ = (char)(c))) +void luaL_addchar(luaL_Buffer* B, char c) +{ + if (B.p < B.buffer.ptr + LUAL_BUFFERSIZE || (luaL_prepbuffer(B))) + { + *B.p = c; + B.p++; + } +} + +/* compatibility only */ +//C #define luaL_putchar(B,c) luaL_addchar(B,c) +alias luaL_addchar luaL_putchar; + +//C #define luaL_addsize(B,n) ((B)->p += (n)) +void luaL_addsize(luaL_Buffer* B, int n) { B.p += n; } + +//C LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +void luaL_buffinit(lua_State *L, luaL_Buffer *B); +//C LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +char * luaL_prepbuffer(luaL_Buffer *B); +//C LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l); +//C LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +void luaL_addstring(luaL_Buffer *B, const char *s); +//C LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +void luaL_addvalue(luaL_Buffer *B); +//C LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +void luaL_pushresult(luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +//C #define LUA_NOREF (-2) +const LUA_NOREF = -2; +//C #define LUA_REFNIL (-1) +const LUA_REFNIL = -1; + +//C #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) +void lua_ref(lua_State* L, int lock) { lock ? luaL_ref(L, LUA_REGISTRYINDEX) : lua_pushstring(L, "unlocked reference are obsolete"); lua_error(L); } + +//C #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) +void lua_unref(lua_State* L, int _ref) { luaL_unref(L, LUA_REGISTRYINDEX, _ref); } + +//C #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) +void lua_getref(lua_State* L, int _ref) { lua_rawgeti(L, LUA_REGISTRYINDEX, _ref); } + + +//C #define luaL_reg luaL_Reg + +alias luaL_Reg luaL_reg; +//C #endif + + diff --git a/source/luad/c/lua.d b/source/luad/c/lua.d new file mode 100644 index 0000000..bc3cd8f --- /dev/null +++ b/source/luad/c/lua.d @@ -0,0 +1,559 @@ +/* Converted to D from lua.h by htod */ +module luad.c.lua; +import core.vararg; +import luad.c.luaconf; + +/* +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + +//C #ifndef lua_h +//C #define lua_h + +//C #include +//C #include + +//C #include "luaconf.h" +//import luaconf; +import luad.c.lauxlib; + +extern (C): + +//C #define LUA_VERSION "Lua 5.1" +string LUA_VERSION = "Lua 5.1"; +//C #define LUA_RELEASE "Lua 5.1.2" +string LUA_RELEASE = "Lua 5.1.2"; +//C #define LUA_VERSION_NUM 501 +//C #define LUA_COPYRIGHT "Copyright (C) 1994-2007 Lua.org, PUC-Rio" +string LUA_COPYRIGHT = "Copyright (C) 1994-2007 Lua.org, PUC-Rio"; +enum LUA_VERSION_NUM = 501; +//C #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" +string LUA_AUTHORS = "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"; + + +/* mark for precompiled code (`Lua') */ +//C #define LUA_SIGNATURE "\033Lua" +const char[] LUA_SIGNATURE = "\033Lua"; + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +//C #define LUA_MULTRET (-1) +const LUA_MULTRET = -1; + + +/* +** pseudo-indices +*/ +//C #define LUA_REGISTRYINDEX (-10000) +const LUA_REGISTRYINDEX = -10000; +//C #define LUA_ENVIRONINDEX (-10001) +const LUA_ENVIRONINDEX = -10001; +//C #define LUA_GLOBALSINDEX (-10002) +const LUA_GLOBALSINDEX = -10002; +//C #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) +int lua_upvalueindex (int i) { return LUA_GLOBALSINDEX-i; } + + +/* thread status; 0 is OK */ +//C #define LUA_YIELD 1 +//C #define LUA_ERRRUN 2 +const LUA_YIELD = 1; +//C #define LUA_ERRSYNTAX 3 +const LUA_ERRRUN = 2; +//C #define LUA_ERRMEM 4 +const LUA_ERRSYNTAX = 3; +//C #define LUA_ERRERR 5 +const LUA_ERRMEM = 4; + +const LUA_ERRERR = 5; + +//C typedef struct lua_State lua_State; +struct lua_State {} + +//C typedef int (*lua_CFunction) (lua_State *L); +alias int function(lua_State *L) lua_CFunction; + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +//C typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); +alias char * function(lua_State *L, void *ud, size_t *sz)lua_Reader; + +//C typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); +alias int function(lua_State *L, const void *p, size_t sz, void *ud)lua_Writer; + + +/* +** prototype for memory-allocation functions +*/ +//C typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); +alias void * function(void *ud, void *ptr, size_t osize, size_t nsize)lua_Alloc; + + +/* +** basic types +*/ +//C #define LUA_TNONE (-1) +const LUA_TNONE = -1; + +//C #define LUA_TNIL 0 +//C #define LUA_TBOOLEAN 1 +const LUA_TNIL = 0; +//C #define LUA_TLIGHTUSERDATA 2 +const LUA_TBOOLEAN = 1; +//C #define LUA_TNUMBER 3 +const LUA_TLIGHTUSERDATA = 2; +//C #define LUA_TSTRING 4 +const LUA_TNUMBER = 3; +//C #define LUA_TTABLE 5 +const LUA_TSTRING = 4; +//C #define LUA_TFUNCTION 6 +const LUA_TTABLE = 5; +//C #define LUA_TUSERDATA 7 +const LUA_TFUNCTION = 6; +//C #define LUA_TTHREAD 8 +const LUA_TUSERDATA = 7; + +const LUA_TTHREAD = 8; + + +/* minimum Lua stack available to a C function */ +//C #define LUA_MINSTACK 20 + +const LUA_MINSTACK = 20; + +/* +** generic extra include file +*/ +//C #if defined(LUA_USER_H) +//C #include LUA_USER_H +//C #endif + + +/* type of numbers in Lua */ +//C typedef LUA_NUMBER lua_Number; +alias double lua_Number; + + +/* type for integer functions */ +//C typedef LUA_INTEGER lua_Integer; +alias ptrdiff_t lua_Integer; + + + +/* +** state manipulation +*/ +//C LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +lua_State * lua_newstate(lua_Alloc f, void *ud); +//C LUA_API void (lua_close) (lua_State *L); +void lua_close(lua_State *L); +//C LUA_API lua_State *(lua_newthread) (lua_State *L); +lua_State * lua_newthread(lua_State *L); + +//C LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); +lua_CFunction lua_atpanic(lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +//C LUA_API int (lua_gettop) (lua_State *L); +int lua_gettop(lua_State *L) nothrow; +//C LUA_API void (lua_settop) (lua_State *L, int idx); +void lua_settop(lua_State *L, int idx) nothrow; +//C LUA_API void (lua_pushvalue) (lua_State *L, int idx); +void lua_pushvalue(lua_State *L, int idx) nothrow; +//C LUA_API void (lua_remove) (lua_State *L, int idx); +void lua_remove(lua_State *L, int idx); +//C LUA_API void (lua_insert) (lua_State *L, int idx); +void lua_insert(lua_State *L, int idx); +//C LUA_API void (lua_replace) (lua_State *L, int idx); +void lua_replace(lua_State *L, int idx); +//C LUA_API int (lua_checkstack) (lua_State *L, int sz); +int lua_checkstack(lua_State *L, int sz); + +//C LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); +void lua_xmove(lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +//C LUA_API int (lua_isnumber) (lua_State *L, int idx); +int lua_isnumber(lua_State *L, int idx); +//C LUA_API int (lua_isstring) (lua_State *L, int idx); +int lua_isstring(lua_State *L, int idx); +//C LUA_API int (lua_iscfunction) (lua_State *L, int idx); +int lua_iscfunction(lua_State *L, int idx); +//C LUA_API int (lua_isuserdata) (lua_State *L, int idx); +int lua_isuserdata(lua_State *L, int idx); +//C LUA_API int (lua_type) (lua_State *L, int idx); +int lua_type(lua_State *L, int idx) nothrow; +//C LUA_API const char *(lua_typename) (lua_State *L, int tp); +char * lua_typename(lua_State *L, int tp) nothrow; + +//C LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +bool lua_equal(lua_State *L, int idx1, int idx2); +//C LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +bool lua_rawequal(lua_State *L, int idx1, int idx2); +//C LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); +bool lua_lessthan(lua_State *L, int idx1, int idx2); + +//C LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +lua_Number lua_tonumber(lua_State *L, int idx); +//C LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +lua_Integer lua_tointeger(lua_State *L, int idx); +//C LUA_API int (lua_toboolean) (lua_State *L, int idx); +bool lua_toboolean(lua_State *L, int idx); +//C LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +const(char)* lua_tolstring(lua_State *L, int idx, size_t *len); +//C LUA_API size_t (lua_objlen) (lua_State *L, int idx); +size_t lua_objlen(lua_State *L, int idx); +//C LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +lua_CFunction lua_tocfunction(lua_State *L, int idx); +//C LUA_API void *(lua_touserdata) (lua_State *L, int idx); +void * lua_touserdata(lua_State *L, int idx); +//C LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +lua_State * lua_tothread(lua_State *L, int idx); +//C LUA_API const void *(lua_topointer) (lua_State *L, int idx); +void * lua_topointer(lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +//C LUA_API void (lua_pushnil) (lua_State *L); +void lua_pushnil(lua_State *L); +//C LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +void lua_pushnumber(lua_State *L, lua_Number n); +//C LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +void lua_pushinteger(lua_State *L, lua_Integer n); +//C LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +void lua_pushlstring(lua_State *L, const(char)* s, size_t l); +//C LUA_API void (lua_pushstring) (lua_State *L, const char *s); +void lua_pushstring(lua_State *L, const(char)* s); +//C LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, +//C va_list argp); +const(char)* lua_pushvfstring(lua_State *L, const char *fmt, va_list argp); + + +//C LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +const(char)* lua_pushfstring(lua_State *L, const(char)* fmt,...); +//C LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n); +//C LUA_API void (lua_pushboolean) (lua_State *L, int b); +void lua_pushboolean(lua_State *L, int b); +//C LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +void lua_pushlightuserdata(lua_State *L, void *p); +//C LUA_API int (lua_pushthread) (lua_State *L); +int lua_pushthread(lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +//C LUA_API void (lua_gettable) (lua_State *L, int idx); +void lua_gettable(lua_State *L, int idx); +//C LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +void lua_getfield(lua_State *L, int idx, const(char)* k); +//C LUA_API void (lua_rawget) (lua_State *L, int idx); +void lua_rawget(lua_State *L, int idx); +//C LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +void lua_rawgeti(lua_State *L, int idx, int n) nothrow; +//C LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +void lua_createtable(lua_State *L, int narr, int nrec); +//C LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +void * lua_newuserdata(lua_State *L, size_t sz); +//C LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +int lua_getmetatable(lua_State *L, int objindex); +//C LUA_API void (lua_getfenv) (lua_State *L, int idx); +void lua_getfenv(lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +//C LUA_API void (lua_settable) (lua_State *L, int idx); +void lua_settable(lua_State *L, int idx); +//C LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +void lua_setfield(lua_State *L, int idx, const(char)* k); +//C LUA_API void (lua_rawset) (lua_State *L, int idx); +void lua_rawset(lua_State *L, int idx); +//C LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +void lua_rawseti(lua_State *L, int idx, int n); +//C LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +int lua_setmetatable(lua_State *L, int objindex); +//C LUA_API int (lua_setfenv) (lua_State *L, int idx); +int lua_setfenv(lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +//C LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +void lua_call(lua_State *L, int nargs, int nresults); +//C LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc); +//C LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +int lua_cpcall(lua_State *L, lua_CFunction func, void *ud); +//C LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, +//C const char *chunkname); +int lua_load(lua_State *L, lua_Reader reader, void *dt, const(char)* chunkname); + +//C LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); +int lua_dump(lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +//C LUA_API int (lua_yield) (lua_State *L, int nresults); +int lua_yield(lua_State *L, int nresults); +//C LUA_API int (lua_resume) (lua_State *L, int narg); +int lua_resume(lua_State *L, int narg); +//C LUA_API int (lua_status) (lua_State *L); +int lua_status(lua_State *L); + +/* +** garbage-collection function and options +*/ + +//C #define LUA_GCSTOP 0 +//C #define LUA_GCRESTART 1 +const LUA_GCSTOP = 0; +//C #define LUA_GCCOLLECT 2 +const LUA_GCRESTART = 1; +//C #define LUA_GCCOUNT 3 +const LUA_GCCOLLECT = 2; +//C #define LUA_GCCOUNTB 4 +const LUA_GCCOUNT = 3; +//C #define LUA_GCSTEP 5 +const LUA_GCCOUNTB = 4; +//C #define LUA_GCSETPAUSE 6 +const LUA_GCSTEP = 5; +//C #define LUA_GCSETSTEPMUL 7 +const LUA_GCSETPAUSE = 6; + +const LUA_GCSETSTEPMUL = 7; +//C LUA_API int (lua_gc) (lua_State *L, int what, int data); +int lua_gc(lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +//C LUA_API int (lua_error) (lua_State *L); +int lua_error(lua_State *L); + +//C LUA_API int (lua_next) (lua_State *L, int idx); +int lua_next(lua_State *L, int idx); + +//C LUA_API void (lua_concat) (lua_State *L, int n); +void lua_concat(lua_State *L, int n); + +//C LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +lua_Alloc lua_getallocf(lua_State *L, void **ud); +//C LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); +void lua_setallocf(lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +//C #define lua_pop(L,n) lua_settop(L, -(n)-1) +void lua_pop(lua_State* L, int n) nothrow { lua_settop(L, -(n)-1); } + +//C #define lua_newtable(L) lua_createtable(L, 0, 0) +void lua_newtable(lua_State* L) { lua_createtable(L, 0, 0); } + +//C #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) +void lua_register(lua_State* L, const(char)* n, lua_CFunction f) { lua_pushcfunction(L, f); lua_setglobal(L, n); } + +//C #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) +void lua_pushcfunction(lua_State* L, lua_CFunction f) { lua_pushcclosure(L, f, 0); } + +//C #define lua_strlen(L,i) lua_objlen(L, (i)) +alias lua_objlen lua_strlen; + +//C #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +bool lua_isfunction(lua_State* L, int n) { return lua_type(L, n) == LUA_TFUNCTION; } +//C #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +bool lua_istable(lua_State* L, int n) { return lua_type(L, n) == LUA_TTABLE; } +//C #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +bool lua_islightuserdata(lua_State* L, int n) { return lua_type(L, n) == LUA_TLIGHTUSERDATA; } +//C #define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +bool lua_isnil(lua_State* L, int n) { return lua_type(L, n) == LUA_TNIL; } +//C #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +bool lua_isboolean(lua_State* L, int n) { return lua_type(L, n) == LUA_TBOOLEAN; } +//C #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +bool lua_isthread(lua_State* L, int n) { return lua_type(L, n) == LUA_TTHREAD; } +//C #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +bool lua_isnone(lua_State* L, int n) { return lua_type(L, n) == LUA_TNONE; } +//C #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) +bool lua_isnoneornil(lua_State* L, int n) { return lua_type(L, n) <= 0; } + +//C #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +void lua_pushliteral(lua_State* L, string s) { lua_pushlstring(L, s.ptr, s.length); } + +//C #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +void lua_setglobal(lua_State* L, const(char)* s) { lua_setfield(L, LUA_GLOBALSINDEX, s); } + +//C #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) +void lua_getglobal(lua_State* L, const(char)* s) { lua_getfield(L, LUA_GLOBALSINDEX, s); } + +//C #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) +const(char)* lua_tostring(lua_State* L, int i) { return lua_tolstring(L, i, null); } + + + +/* +** compatibility macros and functions +*/ + +//C #define lua_open() luaL_newstate() +alias luaL_newstate lua_open; + +//C #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +void lua_getregistry(lua_State* L) { lua_pushvalue(L, LUA_REGISTRYINDEX); } + +//C #define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) +int lua_getgccount(lua_State* L) { return lua_gc(L, LUA_GCCOUNT, 0); } + +//C #define lua_Chunkreader lua_Reader +//C #define lua_Chunkwriter lua_Writer +alias lua_Reader lua_Chunkreader; + +alias lua_Writer lua_Chunkwriter; + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +//C #define LUA_HOOKCALL 0 +//C #define LUA_HOOKRET 1 +const LUA_HOOKCALL = 0; +//C #define LUA_HOOKLINE 2 +const LUA_HOOKRET = 1; +//C #define LUA_HOOKCOUNT 3 +const LUA_HOOKLINE = 2; +//C #define LUA_HOOKTAILRET 4 +const LUA_HOOKCOUNT = 3; + +const LUA_HOOKTAILRET = 4; + +/* +** Event masks +*/ +//C #define LUA_MASKCALL (1 << LUA_HOOKCALL) +const LUA_MASKCALL = 1 << LUA_HOOKCALL; +//C #define LUA_MASKRET (1 << LUA_HOOKRET) +const LUA_MASKRET = 1 << LUA_HOOKRET; +//C #define LUA_MASKLINE (1 << LUA_HOOKLINE) +const LUA_MASKLINE = 1 << LUA_HOOKLINE; +//C #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) +const LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT; + +//C typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +//C typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); +alias void function(lua_State *L, lua_Debug *ar)lua_Hook; + + +//C LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +int lua_getstack(lua_State *L, int level, lua_Debug *ar); +//C LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +int lua_getinfo(lua_State *L, const(char)* what, lua_Debug *ar); +//C LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +const(char)* lua_getlocal(lua_State *L, lua_Debug *ar, int n); +//C LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +const(char)* lua_setlocal(lua_State *L, lua_Debug *ar, int n); +//C LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +const(char)* lua_getupvalue(lua_State *L, int funcindex, int n); +//C LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); +const(char)* lua_setupvalue(lua_State *L, int funcindex, int n); + +//C LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +int lua_sethook(lua_State *L, lua_Hook func, int mask, int count); +//C LUA_API lua_Hook lua_gethook (lua_State *L); +lua_Hook lua_gethook(lua_State *L); +//C LUA_API int lua_gethookmask (lua_State *L); +int lua_gethookmask(lua_State *L); +//C LUA_API int lua_gethookcount (lua_State *L); +int lua_gethookcount(lua_State *L); + + +//C struct lua_Debug { +//C int event; +//C const char *name; /* (n) */ +//C const char *namewhat; /* (n) `global', `local', `field', `method' */ +//C const char *what; /* (S) `Lua', `C', `main', `tail' */ +//C const char *source; /* (S) */ +//C int currentline; /* (l) */ +//C int nups; /* (u) number of upvalues */ +//C int linedefined; /* (S) */ +//C int lastlinedefined; /* (S) */ +//C char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ +//C int i_ci; /* active function */ +//C }; +struct lua_Debug +{ + int event; + const char *name; + const char *namewhat; + const char *what; + const char *source; + int currentline; + int nups; + int linedefined; + int lastlinedefined; + char [LUA_IDSIZE]short_src; + int i_ci; +} + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2007 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +//C #endif diff --git a/source/luad/c/luaconf.d b/source/luad/c/luaconf.d new file mode 100644 index 0000000..abf82a3 --- /dev/null +++ b/source/luad/c/luaconf.d @@ -0,0 +1,780 @@ +/* Converted to D from luaconf.h by htod */ +module luad.c.luaconf; +/* +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +//C #ifndef lconfig_h +//C #define lconfig_h + +//C #include +//import std.c.limits; +//C #include +//import std.c.stddef; + +extern (C): + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +//C #if defined(__STRICT_ANSI__) +//C #define LUA_ANSI +//C #endif + + +//C #if !defined(LUA_ANSI) && defined(_WIN32) +//C #define LUA_WIN +//C #endif + +//C #if defined(LUA_USE_LINUX) +//C #define LUA_USE_POSIX +//C #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +//C #define LUA_USE_READLINE /* needs some extra libraries */ +//C #endif + +//C #if defined(LUA_USE_MACOSX) +//C #define LUA_USE_POSIX +//C #define LUA_DL_DYLD /* does not need extra library */ +//C #endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +//C #if defined(LUA_USE_POSIX) +//C #define LUA_USE_MKSTEMP +//C #define LUA_USE_ISATTY +//C #define LUA_USE_POPEN +//C #define LUA_USE_ULONGJMP +//C #endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +//C #define LUA_PATH "LUA_PATH" +//C #define LUA_CPATH "LUA_CPATH" +//C #define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +//C #if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +//C #define LUA_LDIR "!\\lua\\" +//C #define LUA_CDIR "!\\" +//C #define LUA_PATH_DEFAULT ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +//C #define LUA_CPATH_DEFAULT ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +//C #else +//C #define LUA_ROOT "/usr/local/" +//C #define LUA_LDIR LUA_ROOT "share/lua/5.1/" +//C #define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +//C #define LUA_PATH_DEFAULT "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +//C #define LUA_CPATH_DEFAULT "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" +//C #endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +//C #if defined(_WIN32) +//C #define LUA_DIRSEP "\\" +//C #else +//C #define LUA_DIRSEP "/" +//C #endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +//C #define LUA_PATHSEP ";" +//C #define LUA_PATH_MARK "?" +//C #define LUA_EXECDIR "!" +//C #define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +//C #define LUA_INTEGER ptrdiff_t + +alias ptrdiff_t LUA_INTEGER; + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +//C #if defined(LUA_BUILD_AS_DLL) + +//C #if defined(LUA_CORE) || defined(LUA_LIB) +//C #define LUA_API __declspec(dllexport) +//C #else +//C #define LUA_API __declspec(dllimport) +//C #endif + +//C #else + +//C #define LUA_API extern + +// alias extern LUA_API; +//C #endif + +/* more often than not the libs go together with the core */ +//C #define LUALIB_API LUA_API + +//alias LUA_API LUALIB_API; + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +//C #if defined(luaall_c) +//C #define LUAI_FUNC static +//C #define LUAI_DATA /* empty */ + +//C #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && defined(__ELF__) +//C #define LUAI_FUNC __attribute__((visibility("hidden"))) extern +//C #define LUAI_DATA LUAI_FUNC + +//C #else +//C #define LUAI_FUNC extern +//C #define LUAI_DATA extern +//alias extern LUAI_FUNC; +//C #endif +//alias extern LUAI_DATA; + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +//C #define LUA_QL(x) "'" x "'" +//C #define LUA_QS LUA_QL("%s") +enum LUA_QS = "'%s'"; + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +//C #define LUA_IDSIZE 60 + +const LUA_IDSIZE = 60; + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +//C #if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +//C #if defined(LUA_USE_ISATTY) +//C #include +//C #define lua_stdin_is_tty() isatty(0) +//C #elif defined(LUA_WIN) +//C #include +//C #include +//C #define lua_stdin_is_tty() _isatty(_fileno(stdin)) +//C #else +//C #define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +//C #endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +//C #define LUA_PROMPT "> " +//C #define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +//C #define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +//C #define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +//C #if defined(LUA_USE_READLINE) +//C #include +//C #include +//C #include +//C #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +//C #define lua_saveline(L,idx) if (lua_strlen(L,idx) > 0) /* non-empty line? */ add_history(lua_tostring(L, idx)); /* add it to history */ +//C #define lua_freeline(L,b) ((void)L, free(b)) +//C #else +//C #define lua_readline(L,b,p) ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +//C #define lua_saveline(L,idx) { (void)L; (void)idx; } +//C #define lua_freeline(L,b) { (void)L; (void)b; } +//C #endif + +//C #endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +//C #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + +const LUAI_GCPAUSE = 200; + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +//C #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + +const LUAI_GCMUL = 200; + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +//C #undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +//C #undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +//C #define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +//C #define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +//C #define LUA_COMPAT_LSTR 1 + +const LUA_COMPAT_LSTR = 1; +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +//C #define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +//C #define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +//C #if defined(LUA_USE_APICHECK) +//C #include +//C #define luai_apicheck(L,o) { (void)L; assert(o); } +//C #else +//C #define luai_apicheck(L,o) { (void)L; } +//C #endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +//C #if INT_MAX-20 < 32760 +//C #define LUAI_BITSINT 16 +//C #elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +//C #define LUAI_BITSINT 32 +//C #else +const LUAI_BITSINT = 32; +//C #error "you must define LUA_BITSINT with number of bits in an integer" +//C #endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +//C #if LUAI_BITSINT >= 32 +//C #define LUAI_UINT32 unsigned int +//C #define LUAI_INT32 int +//C #define LUAI_MAXINT32 INT_MAX +alias int LUAI_INT32; +//C #define LUAI_UMEM size_t +//alias INT_MAX LUAI_MAXINT32; +//C #define LUAI_MEM ptrdiff_t +alias size_t LUAI_UMEM; +//C #else +alias ptrdiff_t LUAI_MEM; +/* 16-bit ints */ +//C #define LUAI_UINT32 unsigned long +//C #define LUAI_INT32 long +//C #define LUAI_MAXINT32 LONG_MAX +//C #define LUAI_UMEM unsigned long +//C #define LUAI_MEM long +//C #endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +//C #define LUAI_MAXCALLS 20000 + +const LUAI_MAXCALLS = 20000; + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. +*/ +//C #define LUAI_MAXCSTACK 2048 + +const LUAI_MAXCSTACK = 2048; + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +//C #define LUAI_MAXCCALLS 200 + +const LUAI_MAXCCALLS = 200; + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +//C #define LUAI_MAXVARS 200 + +const LUAI_MAXVARS = 200; + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +//C #define LUAI_MAXUPVALUES 60 + +const LUAI_MAXUPVALUES = 60; + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +//C #define LUAL_BUFFERSIZE BUFSIZ + +//alias BUFSIZ LUAL_BUFFERSIZE; +const LUAL_BUFFERSIZE = 16384; // htod suggested this +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +//C #define LUA_NUMBER_DOUBLE +//C #define LUA_NUMBER double + +alias double LUA_NUMBER; +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +//C #define LUAI_UACNUMBER double + +alias double LUAI_UACNUMBER; + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +//C #define LUA_NUMBER_SCAN "%lf" +//C #define LUA_NUMBER_FMT "%.14g" +//C #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +//C #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +//C #define lua_str2number(s,p) strtod((s), (p)) +const LUAI_MAXNUMBER2STR = 32; + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +//C #if defined(LUA_CORE) +//C #include +//C #define luai_numadd(a,b) ((a)+(b)) +//C #define luai_numsub(a,b) ((a)-(b)) +//C #define luai_nummul(a,b) ((a)*(b)) +//C #define luai_numdiv(a,b) ((a)/(b)) +//C #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +//C #define luai_numpow(a,b) (pow(a,b)) +//C #define luai_numunm(a) (-(a)) +//C #define luai_numeq(a,b) ((a)==(b)) +//C #define luai_numlt(a,b) ((a)<(b)) +//C #define luai_numle(a,b) ((a)<=(b)) +//C #define luai_numisnan(a) (!luai_numeq((a), (a))) +//C #endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +//C #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +//C #if defined(_MSC_VER) + +//C #define lua_number2int(i,d) __asm fld d __asm fistp i +//C #define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +//C #else + +//C union luai_Cast { double l_d; long l_l; }; +union luai_Cast +{ + double l_d; + int l_l; +} +//C #define lua_number2int(i,d) { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +//C #define lua_number2integer(i,n) lua_number2int(i, n) + +//C #endif + + +/* this option always works, but may be slow */ +//C #else +//C #define lua_number2int(i,d) ((i)=(int)(d)) +//C #define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +//C #endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +//C #define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +//C #if defined(__cplusplus) +/* C++ exceptions */ +//C #define LUAI_THROW(L,c) throw(c) +//C #define LUAI_TRY(L,c,a) try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +//C #define luai_jmpbuf int /* dummy variable */ + +//C #elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +//C #define LUAI_THROW(L,c) _longjmp((c)->b, 1) +//C #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +//C #define luai_jmpbuf jmp_buf + +//C #else +/* default handling with long jumps */ +//C #define LUAI_THROW(L,c) longjmp((c)->b, 1) +//C #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +//C #define luai_jmpbuf jmp_buf + +//alias jmp_buf luai_jmpbuf; +//C #endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +//C #define LUA_MAXCAPTURES 32 + +const LUA_MAXCAPTURES = 32; + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +//C #if defined(loslib_c) || defined(luaall_c) + +//C #if defined(LUA_USE_MKSTEMP) +//C #include +//C #define LUA_TMPNAMBUFSIZE 32 +//C #define lua_tmpnam(b,e) { strcpy(b, "/tmp/lua_XXXXXX"); e = mkstemp(b); if (e != -1) close(e); e = (e == -1); } + +//C #else +//C #define LUA_TMPNAMBUFSIZE L_tmpnam +//C #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +//C #endif + +//C #endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +//C #if defined(LUA_USE_POPEN) + +//C #define lua_popen(L,c,m) ((void)L, popen(c,m)) +//C #define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +//C #elif defined(LUA_WIN) + +//C #define lua_popen(L,c,m) ((void)L, _popen(c,m)) +//C #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +//C #else + +//C #define lua_popen(L,c,m) ((void)((void)c, m), luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +//C #define lua_pclose(L,file) ((void)((void)L, file), 0) + +//C #endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +//C #if defined(LUA_USE_DLOPEN) +//C #define LUA_DL_DLOPEN +//C #endif + +//C #if defined(LUA_WIN) +//C #define LUA_DL_DLL +//C #endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +//C #define LUAI_EXTRASPACE 0 + +const LUAI_EXTRASPACE = 0; + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +//C #define luai_userstateopen(L) ((void)L) +//C #define luai_userstateclose(L) ((void)L) +//C #define luai_userstatethread(L,L1) ((void)L) +//C #define luai_userstatefree(L) ((void)L) +//C #define luai_userstateresume(L,n) ((void)L) +//C #define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +//C #if defined(LUA_USELONGLONG) + +//C #define LUA_INTFRMLEN "ll" +//C #define LUA_INTFRM_T long long + +//C #else + +//C #define LUA_INTFRMLEN "l" +//C #define LUA_INTFRM_T long + +alias long LUA_INTFRM_T; +//C #endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +//C #endif + diff --git a/source/luad/c/lualib.d b/source/luad/c/lualib.d new file mode 100644 index 0000000..b275a15 --- /dev/null +++ b/source/luad/c/lualib.d @@ -0,0 +1,74 @@ +/* Converted to D from lualib.h by htod */ +module luad.c.lualib; +import luad.c.lua; +/* +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +//C #ifndef lualib_h +//C #define lualib_h + +//C #include "lua.h" + +extern (C): + +/* Key to file-handle type */ +//C #define LUA_FILEHANDLE "FILE*" +const char[] LUA_FILEHANDLE = "FILE*"; + + +//C #define LUA_COLIBNAME "coroutine" +const char[] LUA_COLIBNAME = "coroutine"; +//C LUALIB_API int (luaopen_base) (lua_State *L); +int luaopen_base(lua_State *L); + +//C #define LUA_TABLIBNAME "table" +const char[] LUA_TABLIBNAME = "table"; +//C LUALIB_API int (luaopen_table) (lua_State *L); +int luaopen_table(lua_State *L); + +//C #define LUA_IOLIBNAME "io" +const char[] LUA_IOLIBNAME = "io"; +//C LUALIB_API int (luaopen_io) (lua_State *L); +int luaopen_io(lua_State *L); + +//C #define LUA_OSLIBNAME "os" +const char[] LUA_OSLIBNAME = "os"; +//C LUALIB_API int (luaopen_os) (lua_State *L); +int luaopen_os(lua_State *L); + +//C #define LUA_STRLIBNAME "string" +const char[] LUA_STRLIBNAME = "string"; +//C LUALIB_API int (luaopen_string) (lua_State *L); +int luaopen_string(lua_State *L); + +//C #define LUA_MATHLIBNAME "math" +const char[] LUA_MATHLIBNAME = "math"; +//C LUALIB_API int (luaopen_math) (lua_State *L); +int luaopen_math(lua_State *L); + +//C #define LUA_DBLIBNAME "debug" +const char[] LUA_DBLIBNAME = "debug"; +//C LUALIB_API int (luaopen_debug) (lua_State *L); +int luaopen_debug(lua_State *L); + +//C #define LUA_LOADLIBNAME "package" +const char[] LUA_LOADLIBNAME = "package"; +//C LUALIB_API int (luaopen_package) (lua_State *L); +int luaopen_package(lua_State *L); + + +/* open all previous libraries */ +//C LUALIB_API void (luaL_openlibs) (lua_State *L); +void luaL_openlibs(lua_State *L); + + + +//C #ifndef lua_assert +//C #define lua_assert(x) ((void)0) +//C #endif + + +//C #endif diff --git a/source/luad/c/tostring.d b/source/luad/c/tostring.d new file mode 100644 index 0000000..3d368d4 --- /dev/null +++ b/source/luad/c/tostring.d @@ -0,0 +1,26 @@ +module luad.c.tostring; + +import luad.c.lua, luad.c.lauxlib; + +const(char)* luaL_tolstring(lua_State* L, int idx, size_t* len) +{ + if(!luaL_callmeta(L, idx, "__tostring")) /* no metamethod? */ + { + switch(lua_type(L, idx)) + { + case LUA_TSTRING, LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx)? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} \ No newline at end of file diff --git a/source/luad/conversions/arrays.d b/source/luad/conversions/arrays.d new file mode 100644 index 0000000..def9fe3 --- /dev/null +++ b/source/luad/conversions/arrays.d @@ -0,0 +1,98 @@ +/** +Internal module for pushing and getting _arrays. +All _arrays with LuaD compatible element types are supported. +*/ +module luad.conversions.arrays; + +import std.traits; +import std.range : ElementType; + +import luad.c.all; +import luad.stack; + +void pushArray(T)(lua_State* L, ref T arr) if (isArray!T) +{ + assert(arr.length <= int.max, "lua_createtable only supports int.max many elements"); + lua_createtable(L, cast(int) arr.length, 0); + foreach(i, v; arr) + { + pushValue(L, i + 1); //Lua tables start at 1, not 0 + pushValue(L, v); + lua_rawset(L, -3); + } +} + +// TODO: do the immutable/const initialization *properly* +T getArray(T)(lua_State* L, int idx) if (isArray!T) +{ + alias ElemType = ElementType!T; + auto len = lua_objlen(L, idx); + + static if(isStaticArray!T) + { + if(len != T.length) + luaL_error(L, "Incorrect number of array elements: %d, expected: %d", len, T.length); + + Unqual!ElemType[T.length] arr; + } + else + auto arr = new Unqual!ElemType[len]; + + foreach(i; 0 .. len) + { + lua_pushinteger(L, i + 1); + lua_gettable(L, idx < 0? idx - 1 : idx); + arr[i] = popValue!ElemType(L); + } + + return cast(T)arr; +} + +void fillStaticArray(T)(lua_State* L, ref T arr) if(isStaticArray!T) +{ + foreach(i, ref elem; arr) + { + elem = getValue!(typeof(elem))(L, cast(int)(-arr.length + i)); + } +} + +void pushStaticArray(T)(lua_State* L, ref T arr) if(isStaticArray!T) +{ + foreach(elem; arr) + pushValue(L, elem); +} + +version(unittest) import luad.testing; + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + { + int[] arr = [1, 2, 3]; + pushValue(L, arr); + assert(lua_istable(L, -1)); + lua_setglobal(L, "array"); + + unittest_lua(L, ` + for i, expected in pairs{1, 2, 3} do + local value = array[i] + assert(value == expected, + ("bad array index: '%s' = '%s' (expected '%s')"):format(i, value, expected) + ) + end + `); + } + + { + unittest_lua(L, `array = {"hello", "from", "lua"}`); + + lua_getglobal(L, "array"); + string[] arr = popValue!(string[])(L); + assert(arr[0] == "hello"); + assert(arr[1] == "from"); + assert(arr[2] == "lua"); + } +} diff --git a/source/luad/conversions/assocarrays.d b/source/luad/conversions/assocarrays.d new file mode 100644 index 0000000..541064c --- /dev/null +++ b/source/luad/conversions/assocarrays.d @@ -0,0 +1,63 @@ +/** +Internal module for pushing and getting associative arrays. +All associative arrays with LuaD compatible key and value types are supported. +For tables with heterogeneous key or value types, use $(D Algebraic) (see $(DPMODULE2 conversions,variant)) keys/values or $(DPREF table,LuaTable). +For string keys and heterogeneous value types, consider using a $(D struct) (see $(DPMODULE2 conversions,structs)). +*/ +module luad.conversions.assocarrays; + +import luad.c.all; +import std.traits; +import luad.stack; + +void pushAssocArray(T, U)(lua_State* L, T[U] aa) +{ + assert(aa.length <= int.max, "lua_createtable only supports int.max many elements"); + lua_createtable(L, 0, cast(int) aa.length); + foreach(key, value; aa) + { + pushValue(L, key); + pushValue(L, value); + lua_rawset(L, -3); + } +} + +T getAssocArray(T)(lua_State* L, int idx) if (isAssociativeArray!T) +{ + T aa; + alias typeof(aa.values[0]) ElemType; + alias typeof(aa.keys[0]) KeyType; + + lua_pushnil(L); + while(lua_next(L, idx < 0? idx - 1 : idx) != 0) + { + aa[getValue!KeyType(L, -2)] = getValue!ElemType(L, -1); + lua_pop(L, 1); + } + + return aa; +} + +version(unittest) import luad.testing; + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + pushValue(L, ["foo": "bar", "hello": "world"]); + lua_setglobal(L, "aa"); + + unittest_lua(L, ` + assert(aa.foo == "bar") + assert(aa.hello == "world") + + aa = {one = 1, two = 2} + `); + + lua_getglobal(L, "aa"); + auto aa = popValue!(uint[string])(L); + assert(aa["one"] == 1); + assert(aa["two"] == 2); +} diff --git a/source/luad/conversions/classes.d b/source/luad/conversions/classes.d new file mode 100644 index 0000000..cc9d78a --- /dev/null +++ b/source/luad/conversions/classes.d @@ -0,0 +1,288 @@ +/** +Internal module for pushing and getting class types. +This feature is still a work in progress, currently, only the simplest of _classes are supported. +See the source code for details. +*/ +module luad.conversions.classes; + +import luad.conversions.functions; + +import luad.c.all; +import luad.stack; +import luad.base; + +import core.memory; + +import std.traits; +import std.string : toStringz; + +extern(C) private int classCleaner(lua_State* L) +{ + GC.removeRoot(lua_touserdata(L, 1)); + return 0; +} + +private void pushMeta(T)(lua_State* L, T obj) +{ + if(luaL_newmetatable(L, T.mangleof.ptr) == 0) + return; + + pushValue(L, T.stringof); + lua_setfield(L, -2, "__dclass"); + + pushValue(L, T.mangleof); + lua_setfield(L, -2, "__dmangle"); + + lua_newtable(L); //__index fallback table + + foreach(member; __traits(derivedMembers, T)) + { + static if(__traits(getProtection, __traits(getMember, T, member)) == "public" && //ignore non-public fields + member != "this" && member != "__ctor" && //do not handle + member != "Monitor" && member != "toHash" && //do not handle + member != "toString" && member != "opEquals" && //handle below + member != "opCmp") //handle below + { + static if(__traits(getOverloads, T.init, member).length > 0 && !__traits(isStaticFunction, mixin("T." ~ member))) + { + pushMethod!(T, member)(L); + lua_setfield(L, -2, toStringz(member)); + } + } + } + + lua_setfield(L, -2, "__index"); + + pushMethod!(T, "toString")(L); + lua_setfield(L, -2, "__tostring"); + + pushMethod!(T, "opEquals")(L); + lua_setfield(L, -2, "__eq"); + + //TODO: handle opCmp here + + + lua_pushcfunction(L, &classCleaner); + lua_setfield(L, -2, "__gc"); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__metatable"); +} + +void pushClassInstance(T)(lua_State* L, T obj) if (is(T == class)) +{ + T* ud = cast(T*)lua_newuserdata(L, obj.sizeof); + *ud = obj; + + pushMeta(L, obj); + lua_setmetatable(L, -2); + + GC.addRoot(ud); +} + +//TODO: handle foreign userdata properly (i.e. raise errors) +T getClassInstance(T)(lua_State* L, int idx) if (is(T == class)) +{ + if(lua_getmetatable(L, idx) == 0) + { + luaL_error(L, "attempt to get 'userdata: %p' as a D object", lua_topointer(L, idx)); + } + + lua_getfield(L, -1, "__dmangle"); //must be a D object + + static if(!is(T == Object)) //must be the right object + { + size_t manglelen; + auto cmangle = lua_tolstring(L, -1, &manglelen); + if(cmangle[0 .. manglelen] != T.mangleof) + { + lua_getfield(L, -2, "__dclass"); + auto cname = lua_tostring(L, -1); + luaL_error(L, `attempt to get instance %s as type "%s"`, cname, toStringz(T.stringof)); + } + } + lua_pop(L, 2); //metatable and metatable.__dmangle + + Object obj = *cast(Object*)lua_touserdata(L, idx); + return cast(T)obj; +} + +template hasCtor(T) +{ + enum hasCtor = __traits(compiles, __traits(getOverloads, T.init, "__ctor")); +} + +// TODO: exclude private members (I smell DMD bugs...) +template isStaticMember(T, string member) +{ + static if(__traits(compiles, mixin("&T." ~ member))) + { + static if(is(typeof(mixin("&T.init." ~ member)) == delegate)) + enum isStaticMember = __traits(isStaticFunction, mixin("T." ~ member)); + else + enum isStaticMember = true; + } + else + enum isStaticMember = false; +} + +// For use as __call +void pushCallMetaConstructor(T)(lua_State* L) +{ + alias typeof(__traits(getOverloads, T.init, "__ctor")) Ctor; + + static T ctor(LuaObject self, ParameterTypeTuple!Ctor args) + { + return new T(args); + } + + pushFunction(L, &ctor); +} + +// TODO: Private static fields are mysteriously pushed without error... +// TODO: __index should be a function querying the static fields directly +void pushStaticTypeInterface(T)(lua_State* L) +{ + lua_newtable(L); + + enum metaName = T.mangleof ~ "_static"; + if(luaL_newmetatable(L, metaName.ptr) == 0) + { + lua_setmetatable(L, -2); + return; + } + + static if(hasCtor!T) + { + pushCallMetaConstructor!T(L); + lua_setfield(L, -2, "__call"); + } + + lua_newtable(L); + + foreach(member; __traits(derivedMembers, T)) + { + static if(isStaticMember!(T, member)) + { + enum isFunction = is(typeof(mixin("T." ~ member)) == function); + + static if(isFunction) + pushValue(L, mixin("&T." ~ member)); + else + pushValue(L, mixin("T." ~ member)); + + lua_setfield(L, -2, member.ptr); + } + } + + lua_setfield(L, -2, "__index"); + + lua_setmetatable(L, -2); +} + +version(unittest) +{ + import luad.testing; + private lua_State* L; +} + +unittest +{ + L = luaL_newstate(); + + static class A + { + private: + string s; + + public: + int n; + + this(int n, string s) + { + this.n = n; + this.s = s; + } + + string foo(){ return s; } + + int bar(int i) + { + return n += i; + } + + void verifyN(int n) + { + assert(this.n == n); + } + } + + static class B : A + { + this(int a, string s) + { + super(a, s); + } + + override string foo() { return "B"; } + + override string toString() { return "B"; } + } + + void addA(in char* name, A a) + { + pushValue(L, a); + lua_setglobal(L, name); + } + + auto a = new A(2, "foo"); + addA("a", a); + + pushValue(L, a.toString()); + lua_setglobal(L, "a_toString"); + + auto b = new B(2, "foo"); + addA("b", b); + addA("otherb", b); + + pushValue(L, (A a) + { + assert(a); + a.bar(2); + }); + lua_setglobal(L, "func"); + + luaL_openlibs(L); + unittest_lua(L, ` + --assert(a.n == 2) + assert(a:bar(2) == 4) + --assert(a.n == 4) + func(a) + assert(a:bar(2) == 8) + + --a.n = 42 + --a:verifyN(42) + --assert(a.n == 42) + + assert(a:foo() == "foo") + assert(tostring(a) == a_toString) + + assert(b:bar(2) == 4) + func(b) + assert(b:bar(2) == 8) + + assert(b:foo() == "B") + assert(tostring(b) == "B") + + assert(a ~= b) + assert(b == otherb) + `); + + pushValue(L, cast(B)null); + lua_setglobal(L, "c"); + unittest_lua(L, `assert(c == nil)`); + + pushValue(L, (B b) => assert(b is null)); + lua_setglobal(L, "checkNull"); + unittest_lua(L, `checkNull(nil)`); +} diff --git a/source/luad/conversions/functions.d b/source/luad/conversions/functions.d new file mode 100644 index 0000000..fd4b932 --- /dev/null +++ b/source/luad/conversions/functions.d @@ -0,0 +1,670 @@ +/** +Internal module for pushing and getting _functions and delegates. + +LuaD allows for pushing of all D function or delegate types with return type and parameter types compatible with LuaD (see $(DPMODULE stack)). + +For a fixed number of multiple return values, return a $(STDREF typecons,Tuple) or a static array. For a variable number of return values, return $(MREF LuaVariableReturn). + +As a special case for $(D const(char)[]) parameter types in _functions pushed to Lua, no copy of the string is made when called; take care not to escape such references, they are effectively $(D scope) parameters. +When a copy is desired, use $(D char[]) or $(D string), or $(D dup) or $(D idup) the string manually. + +If a function with the $(D lua_CFunction) signature is encountered, it is pushed directly with no inserted conversions or overhead. + +Typesafe varargs is supported when pushing _functions to Lua, but as of DMD 2.054, compiler bugs prevent getting delegates with varargs from Lua (use $(DPREF lfunction,LuaFunction) instead). +*/ +module luad.conversions.functions; + +import core.memory; +import std.range; +import std.string : toStringz; +import std.traits; +import std.typetuple; + +import luad.c.all; + +import luad.stack; + +private void argsError(lua_State* L, int nargs, ptrdiff_t expected) +{ + lua_Debug debugInfo; + lua_getstack(L, 0, &debugInfo); + lua_getinfo(L, "n", &debugInfo); + luaL_error(L, "call to %s '%s': got %d arguments, expected %d", + debugInfo.namewhat, debugInfo.name, nargs, expected); +} + +template StripHeadQual(T : const(T*)) +{ + alias const(T)* StripHeadQual; +} + +template StripHeadQual(T : const(T[])) +{ + alias const(T)[] StripHeadQual; +} + +template StripHeadQual(T : immutable(T*)) +{ + alias immutable(T)* StripHeadQual; +} + +template StripHeadQual(T : immutable(T[])) +{ + alias immutable(T)[] StripHeadQual; +} + +template StripHeadQual(T : T[]) +{ + alias T[] StripHeadQual; +} + +template StripHeadQual(T : T*) +{ + alias T* StripHeadQual; +} + +template StripHeadQual(T : T[N], size_t N) +{ + alias T[N] StripHeadQual; +} + +template StripHeadQual(T) +{ + alias T StripHeadQual; +} + +template FillableParameterTypeTuple(T) +{ + alias staticMap!(StripHeadQual, ParameterTypeTuple!T) FillableParameterTypeTuple; +} + +template BindableReturnType(T) +{ + alias StripHeadQual!(ReturnType!T) BindableReturnType; +} + +//Call with or without return value, propagating Exceptions as Lua errors. +//This should rather be throwing a userdata with __tostring and a reference to +//the thrown exception, as it is now, everything but the error type and message is lost. +int callFunction(T)(lua_State* L, T func, ParameterTypeTuple!T args) + if(!is(BindableReturnType!T == const) && + !is(BindableReturnType!T == immutable)) +{ + alias BindableReturnType!T RetType; + enum hasReturnValue = !is(RetType == void); + + static if(hasReturnValue) + RetType ret; + + try + { + static if(hasReturnValue) + ret = func(args); + else + func(args); + } + catch(Exception e) + { + luaL_error(L, "%s", toStringz(e.toString())); + } + + static if(hasReturnValue) + return pushReturnValues(L, ret); + else + return 0; +} + +// Ditto, but wrap the try-catch in a nested function because the return value's +// declaration and initialization cannot be separated. +int callFunction(T)(lua_State* L, T func, ParameterTypeTuple!T args) + if(is(BindableReturnType!T == const) || + is(BindableReturnType!T == immutable)) +{ + auto ref call() + { + try + return func(args); + catch(Exception e) + luaL_error(L, "%s", e.toString().toStringz()); + } + + return pushReturnValues(L, call()); +} + +private: + +// TODO: right now, virtual functions on specialized classes can be called with base classes as 'self', not safe! +extern(C) int methodWrapper(T, Class, bool virtual)(lua_State* L) +{ + alias ParameterTypeTuple!T Args; + + static assert ((variadicFunctionStyle!T != Variadic.d && variadicFunctionStyle!T != Variadic.c), + "Non-typesafe variadic functions are not supported."); + + //Check arguments + int top = lua_gettop(L); + + static if (variadicFunctionStyle!T == Variadic.typesafe) + enum requiredArgs = Args.length; + else + enum requiredArgs = Args.length + 1; + + if(top < requiredArgs) + argsError(L, top, requiredArgs); + + Class self = *cast(Class*)luaL_checkudata(L, 1, toStringz(Class.mangleof)); + + static if(virtual) + { + alias ReturnType!T function(Class, Args) VirtualWrapper; + VirtualWrapper func = cast(VirtualWrapper)lua_touserdata(L, lua_upvalueindex(1)); + } + else + { + T func; + func.ptr = cast(void*)self; + func.funcptr = cast(typeof(func.funcptr))lua_touserdata(L, lua_upvalueindex(1)); + } + + //Assemble arguments + static if(virtual) + { + ParameterTypeTuple!VirtualWrapper allArgs; + allArgs[0] = self; + alias allArgs[1..$] args; + } + else + { + Args allArgs; + alias allArgs args; + } + + foreach(i, Arg; Args) + args[i] = getArgument!(T, i)(L, i + 2); + + return callFunction!(typeof(func))(L, func, allArgs); +} + +extern(C) int functionWrapper(T)(lua_State* L) +{ + alias FillableParameterTypeTuple!T Args; + + static assert ((variadicFunctionStyle!T != Variadic.d && variadicFunctionStyle!T != Variadic.c), + "Non-typesafe variadic functions are not supported."); + + //Check arguments + int top = lua_gettop(L); + + static if (variadicFunctionStyle!T == Variadic.typesafe) + enum requiredArgs = Args.length - 1; + else + enum requiredArgs = Args.length; + + if(top < requiredArgs) + argsError(L, top, requiredArgs); + + //Get function + static if(isFunctionPointer!T) + T func = cast(T)lua_touserdata(L, lua_upvalueindex(1)); + else + T func = *cast(T*)lua_touserdata(L, lua_upvalueindex(1)); + + //Assemble arguments + Args args; + foreach(i, Arg; Args) + args[i] = getArgument!(T, i)(L, i + 1); + + return callFunction!T(L, func, args); +} + +extern(C) int functionCleaner(lua_State* L) +{ + GC.removeRoot(lua_touserdata(L, 1)); + return 0; +} + +public: + +void pushFunction(T)(lua_State* L, T func) if (isSomeFunction!T) +{ + static if(isFunctionPointer!T) + lua_pushlightuserdata(L, func); + else + { + T* udata = cast(T*)lua_newuserdata(L, T.sizeof); + *udata = func; + + GC.addRoot(udata); + + if(luaL_newmetatable(L, "__dcall") == 1) + { + lua_pushcfunction(L, &functionCleaner); + lua_setfield(L, -2, "__gc"); + } + + lua_setmetatable(L, -2); + } + + lua_pushcclosure(L, &functionWrapper!T, 1); +} + +// TODO: optimize for non-virtual functions +void pushMethod(Class, string member)(lua_State* L) if (isSomeFunction!(__traits(getMember, Class, member))) +{ + alias typeof(mixin("&Class.init." ~ member)) T; + + // Delay vtable lookup until the right time + static ReturnType!T virtualWrapper(Class self, ParameterTypeTuple!T args) + { + return mixin("self." ~ member)(args); + } + + lua_pushlightuserdata(L, &virtualWrapper); + lua_pushcclosure(L, &methodWrapper!(T, Class, true), 1); +} + +/** + * Currently this function allocates a reference in the registry that is never deleted, + * one for each call... see code comments + */ +T getFunction(T)(lua_State* L, int idx) if (is(T == delegate)) +{ + auto func = new class + { + int lref; + this() + { + lua_pushvalue(L, idx); + lref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + //Alright... how to fix this? + //The problem is that this object tends to be finalized after L is freed (by LuaState's destructor or otherwise). + //If you have a good solution to the problem of dangling references to a lua_State, + //please contact me :) + + /+~this() + { + luaL_unref(L, LUA_REGISTRYINDEX, lref); + }+/ + + void push() + { + lua_rawgeti(L, LUA_REGISTRYINDEX, lref); + } + }; + + alias ReturnType!T RetType; + alias ParameterTypeTuple!T Args; + + return delegate RetType(Args args) + { + func.push(); + foreach(arg; args) + pushValue(L, arg); + + return callWithRet!RetType(L, args.length); + }; +} + +/** + * Type for efficiently returning a variable number of return values + * from a function. + * + * Use $(D variableReturn) to instantiate it. + * Params: + * Range = any input range + */ +struct LuaVariableReturn(Range) if(isInputRange!Range) +{ + alias WrappedType = Range; /// The type of the wrapped input range. + Range returnValues; /// The wrapped input range. +} + +/** + * Create a LuaVariableReturn object for efficiently returning + * a variable number of values from a function. + * Params: + * returnValues = any input range + * Example: +----------------------------- + LuaVariableReturn!(uint[]) makeList(uint n) + { + uint[] list; + + foreach(i; 1 .. n + 1) + { + list ~= i; + } + + return variableReturn(list); + } + + lua["makeList"] = &makeList; + + lua.doString(` + local one, two, three, four = makeList(4) + assert(one == 1) + assert(two == 2) + assert(three == 3) + assert(four == 4) + `); +----------------------------- + */ +LuaVariableReturn!Range variableReturn(Range)(Range returnValues) + if(isInputRange!Range) +{ + return typeof(return)(returnValues); +} + +version(unittest) +{ + import luad.testing; + import std.typecons; + private lua_State* L; +} + +unittest +{ + L = luaL_newstate(); + luaL_openlibs(L); + + //functions + static const(char)[] func(const(char)[] s) + { + return "Hello, " ~ s; + } + + pushValue(L, &func); + assert(lua_isfunction(L, -1)); + lua_setglobal(L, "sayHello"); + + unittest_lua(L, ` + local ret = sayHello("foo") + local expect = "Hello, foo" + assert(ret == expect, + ("sayHello return type - got '%s', expected '%s'"):format(ret, expect) + ) + `); + + static uint countSpaces(const(char)[] s) + { + uint n = 0; + foreach(dchar c; s) + if(c == ' ') + ++n; + + return n; + } + + pushValue(L, &countSpaces); + assert(lua_isfunction(L, -1)); + lua_setglobal(L, "countSpaces"); + + unittest_lua(L, ` + assert(countSpaces("Hello there, world!") == 2) + `); + + //delegates + double curry = 3.14 * 2; + double closure(double x) + { + return curry * x; + } + + pushValue(L, &closure); + assert(lua_isfunction(L, -1)); + lua_setglobal(L, "circle"); + + unittest_lua(L, ` + assert(circle(2) == 3.14 * 4, "closure return type mismatch!") + `); + + // Const parameters + static bool isEmpty(const(char[]) str) { return str.length == 0; } + static bool isEmpty2(in char[] str) { return str.length == 0; } + + pushValue(L, &isEmpty); + lua_setglobal(L, "isEmpty"); + + pushValue(L, &isEmpty2); + lua_setglobal(L, "isEmpty2"); + + unittest_lua(L, ` + assert(isEmpty("")) + assert(isEmpty2("")) + assert(not isEmpty("a")) + assert(not isEmpty2("a")) + `); + + // Immutable parameters + static immutable(char[]) returnArg(immutable(char[]) str) { return str; } + + pushValue(L, &returnArg); + lua_setglobal(L, "returnArg"); + + unittest_lua(L, `assert(returnArg("foo") == "foo")`); +} + +version(unittest) import luad.base; + +// multiple return values +unittest +{ + // tuple returns + auto nameInfo = ["foo"]; + auto ageInfo = [42]; + + alias Tuple!(string, "name", uint, "age") GetInfoResult; + GetInfoResult getInfo(int idx) + { + GetInfoResult result; + result.name = nameInfo[idx]; + result.age = ageInfo[idx]; + return result; + } + + pushValue(L, &getInfo); + lua_setglobal(L, "getInfo"); + + unittest_lua(L, ` + local name, age = getInfo(0) + assert(name == "foo") + assert(age == 42) + `); + + // static array returns + static string[2] getName() + { + string[2] ret; + ret[0] = "Foo"; + ret[1] = "Bar"; + return ret; + } + + pushValue(L, &getName); + lua_setglobal(L, "getName"); + + unittest_lua(L, ` + local first, last = getName() + assert(first == "Foo") + assert(last == "Bar") + `); + + // variable length returns + LuaVariableReturn!(uint[]) makeList(uint n) + { + uint[] list; + + foreach(i; 1 .. n + 1) + { + list ~= i; + } + + return variableReturn(list); + } + + auto makeList2(uint n) + { + return variableReturn(iota(1, n + 1)); + } + + pushValue(L, &makeList); + lua_setglobal(L, "makeList"); + pushValue(L, &makeList2); + lua_setglobal(L, "makeList2"); + + unittest_lua(L, ` + for i, f in pairs{makeList, makeList2} do + local one, two, three, four = f(4) + assert(one == 1) + assert(two == 2) + assert(three == 3) + assert(four == 4) + end + `); +} + +// Variadic function arguments +unittest +{ + static string concat(const(char)[][] pieces...) + { + string result; + foreach(piece; pieces) + result ~= piece; + return result; + } + + pushValue(L, &concat); + lua_setglobal(L, "concat"); + + unittest_lua(L, ` + local whole = concat("he", "llo", ", ", "world!") + assert(whole == "hello, world!") + `); + + //Test with zero parameters. + unittest_lua(L, ` + local blank = concat() + assert (string.len(blank) == 0) + `); + + static const(char)[] concat2(char separator, const(char)[][] pieces...) + { + if(pieces.length == 0) + return ""; + + string result; + foreach(piece; pieces[0..$-1]) + result ~= piece ~ separator; + + return result ~ pieces[$-1]; + } + + pushValue(L, &concat2); + lua_setglobal(L, "concat2"); + + unittest_lua(L, ` + local whole = concat2(",", "one", "two", "three", "four") + assert(whole == "one,two,three,four") + `); + + //C- and D-style variadic versions of concat for + //future use if/when these are supported. + + //C varargs require at least one fixed argument. + import core.vararg; + // C-style varargs broken on Linux for 2.066.1? + version(none) extern(C) static string concat_cvar (size_t count, ...) + { + string result; + + va_list args; + + va_start(args, count); + + foreach(immutable i; 0 .. count) + { + auto arg = va_arg!LuaObject(args); + result ~= arg.toString(); + } + + va_end(args); + + return result; + } + + //D-style variadics have an _arguments array that specifies + //the type of each passed argument. + static string concat_dvar (...) { + string result; + + foreach (argtype; _arguments) { + assert (argtype == typeid(LuaObject)); + auto arg = va_arg!(LuaObject)(_argptr); + + result ~= arg.toString(); + } + + return result; + } +} + +// get delegates from Lua +unittest +{ + lua_getglobal(L, "string"); + lua_getfield(L, -1, "match"); + auto match = popValue!(string delegate(string, string))(L); + lua_pop(L, 1); + + auto result = match("foobar@example.com", "([^@]+)@example.com"); + assert(result == "foobar"); + + // multiple return values + luaL_dostring(L, `function multRet(a) return "foo", a end`); + lua_getglobal(L, "multRet"); + auto multRet = popValue!(Tuple!(string, int) delegate(int))(L); + + auto results = multRet(42); + assert(results[0] == "foo"); + assert(results[1] == 42); +} + +// Nested call stack testing +unittest +{ + alias string delegate(string) MyFun; + + MyFun[string] funcs; + + pushValue(L, (string name, MyFun fun) { + funcs[name] = fun; + }); + lua_setglobal(L, "addFun"); + + pushValue(L, (string name, string arg) { + auto top = lua_gettop(L); + auto result = funcs[name](arg); + assert(lua_gettop(L) == top); + return result; + }); + lua_setglobal(L, "callFun"); + + auto top = lua_gettop(L); + + luaL_dostring(L, q{ + addFun("echo", function(s) return s end) + local result = callFun("echo", "test") + assert(result == "test") + }); + + assert(lua_gettop(L) == top); +} + +unittest +{ + assert(lua_gettop(L) == 0); + lua_close(L); +} diff --git a/source/luad/conversions/structs.d b/source/luad/conversions/structs.d new file mode 100644 index 0000000..6da6164 --- /dev/null +++ b/source/luad/conversions/structs.d @@ -0,0 +1,137 @@ +/** +Internal module for pushing and getting _structs. + +A struct is treated as a table layout schema. +Pushing a struct to Lua will create a table and fill it with key-value pairs - corresponding to struct fields - from the struct; the field name becomes the table key as a string. +Struct methods are treated as if they were delegate fields pointing to the method. +For an example, see the "Configuration File" example on the $(LINK2 $(REFERENCETOP),front page). +*/ +module luad.conversions.structs; + +import luad.c.all; + +import luad.stack; + +private template isInternal(string field) +{ + enum isInternal = field.length >= 2 && field[0..2] == "__"; +} + +//TODO: ignore static fields, post-blits, destructors, etc? +void pushStruct(T)(lua_State* L, ref T value) if (is(T == struct)) +{ + lua_createtable(L, 0, value.tupleof.length); + + foreach(field; __traits(allMembers, T)) + { + static if(!isInternal!field && + field != "this" && + field != "opAssign") + { + pushValue(L, field); + + enum isMemberFunction = mixin("is(typeof(&value." ~ field ~ ") == delegate)"); + + static if(isMemberFunction) + pushValue(L, mixin("&value." ~ field)); + else + pushValue(L, mixin("value." ~ field)); + + lua_settable(L, -3); + } + } +} + +T getStruct(T)(lua_State* L, int idx) if(is(T == struct)) +{ + T s; + fillStruct(L, idx, s); + return s; +} + +void fillStruct(T)(lua_State* L, int idx, ref T s) if(is(T == struct)) +{ + foreach(field; __traits(allMembers, T)) + { + static if(field != "this" && !isInternal!(field)) + { + static if(__traits(getOverloads, T, field).length == 0) + { + lua_getfield(L, idx, field.ptr); + if(lua_isnil(L, -1) == 0) { + mixin("s." ~ field ~ + " = popValue!(typeof(s." ~ field ~ "))(L);"); + } else + lua_pop(L, 1); + } + } + } +} + +version(unittest) +{ + import luad.base; + struct S + { + LuaObject o; + int i; + double n; + string s; + + string f(){ return "foobar"; } + } +} + +unittest +{ + import luad.testing; + + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + pushValue(L, "test"); + auto obj = popValue!LuaObject(L); + + pushValue(L, S(obj, 1, 2.3, "hello")); + assert(lua_istable(L, -1)); + lua_setglobal(L, "struct"); + + unittest_lua(L, ` + for key, expected in pairs{i = 1, n = 2.3, s = "hello"} do + local value = struct[key] + assert(value == expected, + ("bad table pair: '%s' = '%s' (expected '%s')"):format(key, value, expected) + ) + end + + assert(struct.f() == "foobar") + `); + + lua_getglobal(L, "struct"); + S s = getStruct!S(L, -1); + + assert(s.o == obj); + assert(s.i == 1); + assert(s.n == 2.3); + assert(s.s == "hello"); + + lua_pop(L, 1); + + struct S2 + { + string a, b; + } + + unittest_lua(L, ` + incompleteStruct = {a = "foo"} + `); + + lua_getglobal(L, "incompleteStruct"); + S2 s2 = getStruct!S2(L, -1); + + assert(s2.a == "foo"); + assert(s2.b == null); + + lua_pop(L, 1); +} diff --git a/source/luad/conversions/variant.d b/source/luad/conversions/variant.d new file mode 100644 index 0000000..36902dd --- /dev/null +++ b/source/luad/conversions/variant.d @@ -0,0 +1,127 @@ +/** +Internal module for pushing and getting variants (from $(STDMODULE _variant)). +Currently, only $(STDREF _variant,Algebraic) is supported. +*/ +module luad.conversions.variant; + +import luad.c.all; + +import luad.stack; +import luad.base; +import std.traits; +import std.variant; +import std.typetuple; + +void pushVariant(T)(lua_State* L, ref T value) if(isVariant!T) +{ + if(!value.hasValue()) + { + lua_pushnil(L); + return; + } + + foreach(Type; value.AllowedTypes) + { + if(auto v = value.peek!Type) + { + pushValue(L, *v); + return; + } + } + + assert(false); +} + +T getVariant(T)(lua_State* L, int idx) if (isVariant!T) +{ + auto t = lua_type(L, idx); + + foreach(Type; T.AllowedTypes) + if(t == luaTypeOf!Type) + return T(getValue!Type(L, idx)); + + assert(false); // TODO: runtime error +} + +bool isAllowedType(T)(lua_State* L, int idx) { + auto t = lua_type(L, idx); + + foreach(Type; T.AllowedTypes) + if(t == luaTypeOf!Type) + return true; + + return false; +} + +template isVariant(T) +{ + enum isVariant = is(typeof(isVariantImpl(T.init))); + static if(isVariant) + static assert( + T.AllowedTypes.length > 0, + "Variant is not supported - use an instance of VariantN with an explicit AllowedTypes list, such as Algebraic" + ); +} + +private void isVariantImpl(size_t max, AllowedTypes...)(const VariantN!(max, AllowedTypes) v){} + +version(unittest) import luad.testing; + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + version(none) + { + Variant v = 123; + pushValue(L, v); + assert(popValue!int(L) == 123); + } + + alias Algebraic!(real, string, bool) BasicLuaType; + + BasicLuaType v = "test"; + pushValue(L, v); + assert(lua_isstring(L, -1)); + assert(getValue!string(L, -1) == "test"); + assert(popValue!BasicLuaType(L) == "test"); + + v = 2.3L; + pushValue(L, v); + assert(lua_isnumber(L, -1)); + lua_setglobal(L, "num"); + + unittest_lua(L, ` + assert(num == 2.3) + `); + + v = true; + pushValue(L, v); + assert(lua_isboolean(L, -1)); + assert(popValue!bool(L)); + + struct S + { + int i; + double n; + string s; + + void f(){} + } + pushValue(L, Algebraic!(S, int)(S(1, 2.3, "hello"))); + assert(lua_istable(L, -1)); + lua_setglobal(L, "struct"); + + unittest_lua(L, ` + for key, expected in pairs{i = 1, n = 2.3, s = "hello"} do + local value = struct[key] + assert( + value == expected, + ("bad table pair: '%s' = '%s' (expected '%s')"):format(key, value, expected) + ) + end + `); +} + diff --git a/source/luad/dynamic.d b/source/luad/dynamic.d new file mode 100644 index 0000000..2deae8a --- /dev/null +++ b/source/luad/dynamic.d @@ -0,0 +1,171 @@ +module luad.dynamic; + +import luad.c.all; + +import luad.base; +import luad.stack; + +/** + * Represents a reference to a Lua value of any type. + * Supports all operations you can perform on values in Lua. + */ +struct LuaDynamic +{ + /** + * Underlying Lua reference. + * LuaDynamic does not sub-type LuaObject - qualify access to this reference explicitly. + */ + LuaObject object; + + /** + * Perform a Lua method call on this object. + * + * Performs a call similar to calling functions in Lua with the colon operator. + * The name string is looked up in this object and the result is called. This object is prepended + * to the arguments args. + * Params: + * name = _name of method + * args = additional arguments + * Returns: + * All return values + * Examples: + * ---------------- + * auto luaString = lua.wrap!LuaDynamic("test"); + * auto results = luaString.gsub("t", "f"); // opDispatch + * assert(results[0] == "fesf"); + * assert(results[1] == 2); // two instances of 't' replaced + * ---------------- + * Note: + * To call a member named "object", instantiate this function template explicitly. + */ + LuaDynamic[] opDispatch(string name, string file = __FILE__, uint line = __LINE__, Args...)(Args args) + { + // Push self + object.push(); + + auto frame = lua_gettop(object.state); + + // push name and self[name] + lua_pushlstring(object.state, name.ptr, name.length); + lua_gettable(object.state, -2); + + // TODO: How do I properly generalize this to include other types, + // while not stepping on the __call metamethod? + if(lua_isnil(object.state, -1)) + { + lua_pop(object.state, 2); + luaL_error(object.state, "%s:%d: attempt to call method '%s' (a nil value)", file.ptr, line, name.ptr); + } + + // Copy 'this' to the top of the stack + lua_pushvalue(object.state, -2); + + foreach(arg; args) + pushValue(object.state, arg); + + lua_call(object.state, args.length + 1, LUA_MULTRET); + + auto nret = lua_gettop(object.state) - frame; + + auto ret = popStack!LuaDynamic(object.state, nret); + + // Pop self + lua_pop(object.state, 1); + + return ret; + } + + /** + * Call this object. + * This object must either be a function, or have a metatable providing the ___call metamethod. + * Params: + * args = arguments for the call + * Returns: + * Array of return values, or a null array if there were no return values + */ + LuaDynamic[] opCall(Args...)(Args args) + { + auto frame = lua_gettop(object.state); + + object.push(); // Callable + foreach(arg; args) + pushValue(object.state, arg); + + lua_call(object.state, args.length, LUA_MULTRET); + + auto nret = lua_gettop(object.state) - frame; + + return popStack!LuaDynamic(object.state, nret); + } + + /** + * Index this object. + * This object must either be a table, or have a metatable providing the ___index metamethod. + * Params: + * key = _key to lookup + */ + LuaDynamic opIndex(T)(auto ref T key) + { + object.push(); + pushValue(object.state, key); + lua_gettable(object.state, -2); + auto result = getValue!LuaDynamic(object.state, -1); + lua_pop(object.state, 2); + return result; + } + + /** + * Compare the referenced object to another value with Lua's equality semantics. + * If the _other value is not a Lua reference wrapper, it will go through the + * regular D to Lua conversion process first. + * To check for nil, compare against the special constant "nil". + */ + bool opEquals(T)(auto ref T other) + { + object.push(); + static if(is(T == Nil)) + { + scope(success) lua_pop(object.state, 1); + return lua_isnil(object.state, -1) == 1; + } + else + { + pushValue(object.state, other); + scope(success) lua_pop(object.state, 2); + return lua_equal(object.state, -1, -2); + } + } +} + +version(unittest) import luad.testing; + +import std.stdio; + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + luaL_dostring(L, `str = "test"`); + lua_getglobal(L, "str"); + auto luaString = popValue!LuaDynamic(L); + + LuaDynamic[] results = luaString.gsub("t", "f"); + + assert(results[0] == "fesf"); + assert(results[1] == 2); // two instances of 't' replaced + + auto gsub = luaString["gsub"]; + assert(gsub.object.type == LuaType.Function); + + LuaDynamic[] results2 = gsub(luaString, "t", "f"); + assert(results[0] == results2[0]); + assert(results[1] == results2[1]); + assert(results == results2); + + lua_getglobal(L, "thisisnil"); + auto nilRef = popValue!LuaDynamic(L); + + assert(nilRef == nil); +} \ No newline at end of file diff --git a/source/luad/error.d b/source/luad/error.d new file mode 100644 index 0000000..be60e44 --- /dev/null +++ b/source/luad/error.d @@ -0,0 +1,20 @@ +module luad.error; + +/** + * Thrown on Lua panic. + + * This exception is only thrown if there is no protected Lua call (e.g. $(D pcall)) + * to handle the error. Whenever this documentation says a function throws + * a $(D LuaErrorException), no D exception is actually thrown if a Lua error handler is in place. + + * Additionally, exceptions thrown in D functions given to Lua are converted to + * and propagated as Lua errors. You can subvert this by throwing an object not + * deriving from $(D Exception) (i.e. derive from $(D Error), $(D Throwable), etc). + */ +class LuaErrorException : Exception +{ + this(string err, string file = __FILE__, int line = __LINE__) + { + super(err, file, line); + } +} diff --git a/source/luad/lfunction.d b/source/luad/lfunction.d new file mode 100644 index 0000000..4fd6e92 --- /dev/null +++ b/source/luad/lfunction.d @@ -0,0 +1,190 @@ +module luad.lfunction; + +import luad.base; +import luad.table; +import luad.stack; +import luad.conversions.functions; + +import luad.c.all; + +/// Represents a Lua function. +struct LuaFunction +{ + /// LuaFunction sub-types $(DPREF base, LuaObject) through this reference. + LuaObject object; + alias object this; + + version(none) package this(lua_State* L, int idx) + { + LuaObject.checkType(L, idx, LUA_TFUNCTION, "LuaFunction"); + object = LuaObject(L, idx); + } + + /** + * Call this function and collect all return values as + * an array of $(DPREF base, LuaObject) references. + * Examples: + ----------------------- + lua.doString(`function f(...) return ... end`); + auto f = lua.get!LuaFunction("f"); + + LuaObject[] ret = f(1.2, "hello!", true); + + assert(ret[0].to!double() == 1.2); + assert(ret[1].to!string() == "hello!"); + assert(ret[2].to!bool()); + ----------------------- + */ + LuaObject[] opCall(U...)(U args) + { + return call!(LuaVariableReturn!(LuaObject[]))(args).returnValues; + } + + /** + * Call this function. + * Params: + * T = expected return type. + * args = list of arguments. + * Returns: + * Return value of type $(D T), or nothing if $(D T) was unspecified. + * See $(DPMODULE2 conversions,functions) for how to + * catch multiple return values. + * Examples: + * ------------------ + lua.doString(`function ask(question) return 42 end`); + auto ask = lua.get!LuaFunction("ask"); + + auto answer = ask.call!int("What's the answer to life, the universe and everything?"); + assert(answer == 42); + * ------------------ + */ + T call(T = void, U...)(U args) + { + this.push(); + foreach(arg; args) + pushValue(this.state, arg); + + return callWithRet!T(this.state, args.length); + } + + /** + * Set a new environment for this function. + * + * The environment of a function is the table used for looking up non-local (global) variables. + * Params: + * env = new environment + * Examples: + * ------------------- + * lua["foo"] = "bar"; + * auto func = lua.loadString(`return foo`); + * assert(func.call!string() == "bar"); + * + * auto env = lua.wrap(["foo": "test"]); + * func.setEnvironment(env); + * assert(func.call!string() == "test"); + * ------------------- + */ + void setEnvironment(ref LuaTable env) + in { assert(this.state == env.state); } + body + { + this.push(); + env.push(); + lua_setfenv(this.state, -2); + lua_pop(this.state, 1); + } + + /** + * Dump this function as a binary chunk of Lua bytecode to the specified + * writer delegate. Multiple chunks may be produced to dump a single + * function. + * + * Params: + * writer = delegate to forward writing calls to + * + * If the delegate returns $(D false) for any of the chunks, + * the _dump process ends, and the writer won't be called again. + */ + bool dump(scope bool delegate(in void[]) writer) + { + alias typeof(writer) LuaWriter; + + extern(C) static int luaCWriter(lua_State* L, const void* p, size_t sz, void* ud) + { + auto writer = *cast(LuaWriter*)ud; + return writer(p[0..sz]) ? 0 : 1; + } + + this.push(); + auto ret = lua_dump(this.state, &luaCWriter, &writer); + lua_pop(this.state, 1); + return ret == 0; + } +} + +version(unittest) +{ + import luad.testing; + import std.variant; + import std.typecons; +} + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + luaL_openlibs(L); + + lua_getglobal(L, "tostring"); + auto tostring = popValue!LuaFunction(L); + + LuaObject[] ret = tostring(123); + assert(ret[0].to!string() == "123"); + + assert(tostring.call!string(123) == "123"); + + tostring.call(321); + + // Multiple return values + luaL_dostring(L, "function singleRet() return 42 end"); + lua_getglobal(L, "singleRet"); + auto singleRet = popValue!LuaFunction(L); + + auto singleRetResult = singleRet.call!(Tuple!int)(); + assert(singleRetResult[0] == 42); + + alias Algebraic!(string, double) BasicLuaType; + BasicLuaType a = "foo"; + BasicLuaType b = 1.5; + + pushValue(L, [a, b]); + lua_setglobal(L, "test"); + + luaL_dostring(L, "function multRet() return unpack(test) end"); + lua_getglobal(L, "multRet"); + auto multRet = popValue!LuaFunction(L); + + auto result = multRet.call!(Tuple!(string, double))(); + assert(result[0] == a); + assert(result[1] == b); + + unittest_lua(L, `function getName() return "Foo", "Bar" end`); + + lua_getglobal(L, "getName"); + auto getName = popValue!LuaFunction(L); + + string[2] arrayRet = getName.call!(string[2])(); + assert(arrayRet[0] == "Foo"); + assert(arrayRet[1] == "Bar"); + + // setEnvironment + pushValue(L, ["test": [42]]); + auto env = popValue!LuaTable(L); + + lua_getglobal(L, "unpack"); + env["unpack"] = popValue!LuaObject(L); + + multRet.setEnvironment(env); + assert(multRet.call!int() == 42); + +} diff --git a/source/luad/lmodule.d b/source/luad/lmodule.d new file mode 100644 index 0000000..fdf1d0d --- /dev/null +++ b/source/luad/lmodule.d @@ -0,0 +1,60 @@ +module luad.lmodule; + +import luad.state; +import luad.stack; +import luad.conversions.functions; + +import luad.c.lua : lua_State; + +import std.traits; + +// Internal, but needs to be public +extern(C) int openDModule(F)(lua_State* L, F initFunc) +{ + auto lua = new LuaState(L); + + alias ParameterTypeTuple!F Args; + + static assert(Args.length > 0 && Args.length < 3 && + is(Args[0] == LuaState), + "invalid initFunc signature"); + + Args args; + args[0] = lua; + + static if(Args.length == 2) + { + static assert(is(Args[1] : const(char[])), "second parameter to initFunc must be a const string"); + args[1] = getArgument!(F, 1)(L, -1); + } + + return callFunction!F(L, initFunc, args); +} + +/** + * Generate module entry point for use by Lua's $(D require) function. + * + * Params: + * modname = module name. Typically this should be the same as the name of + * the shared library containing this module. Only characters in the set + * $(D [a-zA-Z_]) are allowed. Underscores are used to denote a submodule. + * The module name must be unique for the current executable. + * + * initFunc = module initialization function. Called when the module is loaded. + * Its return value is returned by $(D require) on the Lua side. Its first + * parameter must be of type $(DPREF state,LuaState), which is the state of the calling environment. + * Optionally, there may be a second parameter implicitly convertible to the type + * $(D const(char[])), which is the name of the module to be loaded (useful for submodules). + */ +// TODO: verify modname +template LuaModule(string modname, alias initFunc) +{ + enum LuaModule = "import luad.c.lua : lua_State;" ~ + // The first exported C symbol always gets a preceeding + // underscore on Windows with DMD/OPTLINK, but Lua + // expects "luaopen_*" exactly. + "version(Windows) export extern(C) void _luad_" ~ modname ~ "_systemconvdummy() {}" ~ + "export extern(C) int luaopen_" ~ modname ~ "(lua_State* L) {" ~ + "return openDModule(L, &" ~ __traits(identifier, initFunc) ~ ");" ~ + "}"; +} diff --git a/source/luad/package.d b/source/luad/package.d new file mode 100644 index 0000000..0c52641 --- /dev/null +++ b/source/luad/package.d @@ -0,0 +1,3 @@ +module luad; + +public import luad.all; diff --git a/source/luad/stack.d b/source/luad/stack.d new file mode 100644 index 0000000..d1cf6f5 --- /dev/null +++ b/source/luad/stack.d @@ -0,0 +1,638 @@ +/++ +This internal module, with the help of the luad.conversions package, takes care of converting between D and Lua types. + +The conversion rules are as follows, where conversion goes both ways: +$(DL + $(DT boolean + $(DD $(D bool)) + ) + $(DT number + $(DD $(D lua_Integer) (default $(D int))) + $(DD $(D lua_Number) (default $(D double))) + ) + $(DT string + $(DD $(D string), $(D const(char)[]), $(D char[])) + $(DD $(D const(char)*)) + $(DD $(D char)) + $(DD $(D immutable(void)[]), $(D const(void)[]), $(D void[]) (binary data)) + ) + $(DT table + $(DD associative arrays (see $(DPMODULE2 conversions,assocarrays))) + $(DD arrays (see $(DPMODULE2 conversions,arrays))) + $(DD structs (see $(DPMODULE2 conversions,structs))) + $(DD $(DPREF table,LuaTable)) + ) + $(DT function (see $(DPMODULE2 conversions,functions)) + $(DD function pointers) + $(DD delegates) + $(DD $(DPREF lfunction,LuaFunction)) + ) + $(DT userdata + $(DD classes (see $(DPMODULE2 conversions,classes))) + ) + $(DT nil + $(DD the special identifier $(D nil)) + $(DD $(D null) class references) + ) + $(DT any of the above + $(DD $(DPREF base,LuaObject)) + $(DD $(DPREF dynamic,LuaDynamic)) + $(DD $(D Algebraic), when given a compatible value (see $(DPMODULE2 conversions,variant))) + ) +) + +The conversions are checked in the specified order. For example, even though $(D bool) is implicitly convertible +to $(D lua_Integer), it will be converted to a boolean because boolean has precedence. + +$(D wchar) and $(D dchar) are explicitly disallowed. Lua strings consist of 8-bit characters, if you want to push UTF-16 or UTF-32 strings, convert to UTF-8 first. + +Additionally, the following types are pushable to Lua, but can't be retrieved back: +$(DL + $(DT function + $(DD $(D lua_CFunction)) + ) +) ++/ +module luad.stack; + +import std.range; +import std.traits; +import std.typecons; + +import luad.c.all; + +import luad.base; +import luad.table; +import luad.lfunction; +import luad.dynamic; + +import luad.conversions.functions; +import luad.conversions.arrays; +import luad.conversions.structs; +import luad.conversions.assocarrays; +import luad.conversions.classes; +import luad.conversions.variant; + +/** + * Push a value of any type to the stack. + * Params: + * L = stack to push to + * value = value to push + */ +void pushValue(T)(lua_State* L, T value) +{ + static if(is(T : LuaObject)) + value.push(); + + else static if(is(T == LuaDynamic)) + value.object.push(); + + else static if(is(T == Nil)) + lua_pushnil(L); + + else static if(is(T == bool)) + lua_pushboolean(L, cast(bool)value); + + else static if(is(T == char)) + lua_pushlstring(L, &value, 1); + + else static if(is(T : lua_Integer)) + lua_pushinteger(L, value); + + else static if(is(T : lua_Number)) + lua_pushnumber(L, value); + + else static if(is(T : const(char)[])) + lua_pushlstring(L, value.ptr, value.length); + + else static if(isVoidArray!T) + lua_pushlstring(L, cast(const(char)*)value.ptr, value.length); + + else static if(is(T : const(char)*)) + lua_pushstring(L, value); + + else static if(isVariant!T) + pushVariant(L, value); + + else static if(isAssociativeArray!T) + pushAssocArray(L, value); + + else static if(isArray!T) + pushArray(L, value); + + else static if(is(T == struct)) + pushStruct(L, value); + + // luaCFunction's are directly pushed + else static if(is(T == lua_CFunction) && functionLinkage!T == "C") + lua_pushcfunction(L, value); + + // other functions are wrapped + else static if(isSomeFunction!T) + pushFunction(L, value); + + else static if(is(T == class)) + { + if(value is null) + lua_pushnil(L); + else + pushClassInstance(L, value); + } + else + static assert(false, "Unsupported type `" ~ T.stringof ~ "` in stack push operation"); +} + +template isVoidArray(T) +{ + enum isVoidArray = is(T == void[]) || + is(T == const(void)[]) || + is(T == const(void[])) || + is(T == immutable(void)[]) || + is(T == immutable(void[])); +} + +/** + * Get the associated Lua type for T. + * Returns: Lua type for T + */ +template luaTypeOf(T) +{ + static if(is(T == bool)) + enum luaTypeOf = LUA_TBOOLEAN; + + else static if(is(T == Nil)) + enum luaTypeOf = LUA_TNIL; + + else static if(is(T : const(char)[]) || is(T : const(char)*) || is(T == char) || isVoidArray!T) + enum luaTypeOf = LUA_TSTRING; + + else static if(is(T : lua_Integer) || is(T : lua_Number)) + enum luaTypeOf = LUA_TNUMBER; + + else static if(isSomeFunction!T || is(T == LuaFunction)) + enum luaTypeOf = LUA_TFUNCTION; + + else static if(isArray!T || isAssociativeArray!T || is(T == struct) || is(T == LuaTable)) + enum luaTypeOf = LUA_TTABLE; + + else static if(is(T : Object)) + enum luaTypeOf = LUA_TUSERDATA; + + else + static assert(false, "No Lua type defined for `" ~ T.stringof ~ "`"); +} + +// generic type mismatch message +private void defaultTypeMismatch(lua_State* L, int idx, int expectedType) +{ + luaL_error(L, "expected %s, got %s", lua_typename(L, expectedType), luaL_typename(L, idx)); +} + +// type mismatch for function arguments of unexpected type +private void argumentTypeMismatch(lua_State* L, int idx, int expectedType) +{ + luaL_typerror(L, idx, lua_typename(L, expectedType)); +} + +/** + * Get a value of any type from the stack. + * Params: + * T = type of value + * typeMismatchHandler = function called to produce an error in case of an invalid conversion. + * L = stack to get from + * idx = value stack index + */ +T getValue(T, alias typeMismatchHandler = defaultTypeMismatch)(lua_State* L, int idx) +{ + debug //ensure unchanged stack + { + int _top = lua_gettop(L); + scope(success) assert(lua_gettop(L) == _top); + } + + //ambiguous types + static if(is(T == wchar) || is(T : const(wchar)[]) || + is(T == dchar) || is(T : const(dchar)[])) + { + static assert("Ambiguous type " ~ T.stringof ~ " in stack push operation. Consider converting before pushing."); + } + + static if(!is(T == LuaObject) && !is(T == LuaDynamic) && !isVariant!T) + { + int type = lua_type(L, idx); + enum expectedType = luaTypeOf!T; + + //if a class reference, return null for nil values + static if(is(T : Object)) + { + if(type == LuaType.Nil) + return null; + } + + if(type != expectedType) + typeMismatchHandler(L, idx, expectedType); + } + + static if(is(T == LuaFunction)) // WORKAROUND: bug #6036 + { + LuaFunction func; + func.object = LuaObject(L, idx); + return func; + } + else static if(is(T == LuaDynamic)) // ditto + { + LuaDynamic obj; + obj.object = LuaObject(L, idx); + return obj; + } + else static if(is(T : LuaObject)) + return T(L, idx); + + else static if(is(T == Nil)) + return nil; + + else static if(is(T == bool)) + return lua_toboolean(L, idx); + + else static if(is(T == char)) + return *lua_tostring(L, idx); // TODO: better define this + + else static if(is(T : lua_Integer)) + return cast(T)lua_tointeger(L, idx); + + else static if(is(T : lua_Number)) + return cast(T)lua_tonumber(L, idx); + + else static if(is(T : const(char)[]) || isVoidArray!T) + { + size_t len; + const(char)* str = lua_tolstring(L, idx, &len); + static if(is(T == char[]) || is(T == void[])) + return str[0 .. len].dup; + else + return str[0 .. len].idup; + } + else static if(is(T : const(char)*)) + return lua_tostring(L, idx); + + else static if(isAssociativeArray!T) + return getAssocArray!T(L, idx); + + else static if(isArray!T) + return getArray!T(L, idx); + + else static if(isVariant!T) + { + if(!isAllowedType!T(L, idx)) + luaL_error(L, "Type not allowed in Variant: %s", luaL_typename(L, idx)); + + return getVariant!T(L, idx); + } + else static if(is(T == struct)) + return getStruct!T(L, idx); + + else static if(isSomeFunction!T) + return getFunction!T(L, idx); + + else static if(is(T : Object)) + return getClassInstance!T(L, idx); + + else + { + static assert(false, "Unsupported type `" ~ T.stringof ~ "` in stack read operation"); + } +} + +/** + * Same as calling getValue!(T, typeMismatchHandler)(L, -1), then popping one value from the stack. + * See_Also: $(MREF getValue) + */ +T popValue(T, alias typeMismatchHandler = defaultTypeMismatch)(lua_State* L) +{ + scope(success) lua_pop(L, 1); + return getValue!(T, typeMismatchHandler)(L, -1); +} + +/** + * Pop a number of elements from the stack. + * Params: + * T = element type + * L = stack to pop from + * n = number of elements to pop + * Returns: + * array of popped elements, or a $(D null) array if n = 0 + */ +T[] popStack(T = LuaObject)(lua_State* L, size_t n) +{ + if(n == 0) // Don't allocate an array in this case + return null; + + auto stack = new T[n]; + foreach(i; 0 .. n) + { + stack[i] = getValue!T(L, cast(int)(-n + i)); + } + + lua_pop(L, cast(int)n); + return stack; +} + +/// Get a function argument from the stack. +auto getArgument(T, int narg)(lua_State* L, int idx) +{ + alias ParameterTypeTuple!T Args; + + static if(narg == -1) // varargs causes this + alias ForeachType!(Args[$-1]) Arg; + else + alias Args[narg] Arg; + + enum isVarargs = variadicFunctionStyle!T == Variadic.typesafe; + + static if(isVarargs && narg == Args.length-1) + { + alias Args[narg] LastArg; + alias ForeachType!LastArg ElemType; + + auto top = lua_gettop(L); + auto size = top - idx + 1; + LastArg result = new LastArg(size); + foreach(i; 0 .. size) + { + result[i] = getArgument!(T, -1)(L, idx + i); + } + return result; + } + else static if(is(Arg == const(char)[]) || is(Arg == const(void)[]) || + is(Arg == const(char[])) || is(Arg == const(void[]))) + { + if(lua_type(L, idx) != LUA_TSTRING) + argumentTypeMismatch(L, idx, LUA_TSTRING); + + size_t len; + const(char)* cstr = lua_tolstring(L, idx, &len); + return cstr[0 .. len]; + } + else + return getValue!(Arg, argumentTypeMismatch)(L, idx); +} + +template isVariableReturnType(T : LuaVariableReturn!U, U) +{ + enum isVariableReturnType = true; +} + +template isVariableReturnType(T) +{ + enum isVariableReturnType = false; +} + +/// Used for getting a suitable nresults argument to $(D lua_call) or $(D lua_pcall). +template returnTypeSize(T) +{ + static if(isVariableReturnType!T) + enum returnTypeSize = LUA_MULTRET; + + else static if(isTuple!T) + enum returnTypeSize = T.Types.length; + + else static if(isStaticArray!T) + enum returnTypeSize = T.length; + + else static if(is(T == void)) + enum returnTypeSize = 0; + + else + enum returnTypeSize = 1; +} + +/** + * Pop return values from stack. + * Defaults to $(MREF popValue), but has special handling for $(DPREF2 conversions, functions, LuaVariableReturn), + * $(STDREF typecons, Tuple), static arrays and $(D void). + * Params: + * nret = number of return values + * Returns: + * Return value, collection of return values, or nothing + */ +T popReturnValues(T)(lua_State* L, size_t nret) +{ + static if(isVariableReturnType!T) + return variableReturn(popStack!(ElementType!(T.WrappedType))(L, nret)); + + else static if(isTuple!T) + { + if(nret < T.Types.length) + luaL_error(L, "expected %d return values, got %d", T.Types.length, nret); + + return popTuple!T(L); + } + else static if(isStaticArray!T) + { + T ret; + fillStaticArray(L, ret); + return ret; + } + else static if(is(T == void)) + return; + + else + { + if(nret < 1) + luaL_error(L, "expected return value of type %s, got nil", lua_typename(L, luaTypeOf!T)); + + return popValue!T(L); + } +} + +/** + * Push return values to the stack. + * Defaults to $(MREF pushValue), but has special handling for $(DPREF2 conversions, functions, LuaVariableReturn), + * $(STDREF typecons, Tuple) and static arrays. + */ +int pushReturnValues(T)(lua_State* L, T value) +{ + static if(isVariableReturnType!T) + { + enum calculateLength = !hasLength!(typeof(value.returnValues)); + + static if(calculateLength) + int length; + + foreach(obj; value.returnValues) + { + pushValue(L, obj); + + static if(calculateLength) + ++length; + } + + static if(calculateLength) + return length; + else + return cast(int)value.returnValues.length; + } + else static if(isTuple!T) + { + pushTuple(L, value); + return cast(int)T.Types.length; + } + else static if(isStaticArray!T) + { + pushStaticArray(L, value); + return cast(int)value.length; + } + else + { + pushValue(L, value); + return 1; + } +} + +/// Pops a $(STDREF typecons, Tuple) from the values at the top of the stack. +T popTuple(T)(lua_State* L) if(isTuple!T) +{ + T tup; + foreach(i, Elem; T.Types) + tup[i] = getValue!Elem(L, cast(int)(-T.Types.length + i)); + + lua_pop(L, T.Types.length); + return tup; +} + +/// Pushes all the values in a $(STDREF typecons, Tuple) to the stack. +void pushTuple(T)(lua_State* L, ref T tup) if(isTuple!T) +{ + foreach(i, Elem; T.Types) + pushValue(L, tup[i]); +} + +/** + * Call a Lua function and handle its return values. + * Params: + * T = type of return value or container of return values + * nargs = number of arguments + * Returns: + * Zero, one or all return values as $(D T), taking into account $(D void), + * $(DPREF2 conversions, functions, LuaVariableReturn) and $(STDREF typecons, Tuple) returns + */ +T callWithRet(T)(lua_State* L, int nargs) +{ + static if(isVariableReturnType!T) + auto frame = lua_gettop(L) - nargs - 1; // the size of the stack before arguments and the function + + lua_call(L, nargs, returnTypeSize!T); + + static if(isVariableReturnType!T) + auto nret = lua_gettop(L) - frame; + else + auto nret = returnTypeSize!T; + + return popReturnValues!T(L, nret); +} + +private extern(C) int printf(const(char)* fmt, ...); + +/// Print the Lua stack to $(D stdout). +void printStack(lua_State* L) +{ + auto top = lua_gettop(L); + + foreach(n; 0 .. top) + { + auto str = luaL_tolstring(L, n + 1, null); + printf("\t[%d] %s (%s)\r\n", n + 1, str, luaL_typename(L, n + 1)); + } + + lua_pop(L, top); // luaL_tolstring always pushes one +} + +version(unittest) import luad.testing; + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) lua_close(L); + + // pushValue and popValue + //number + pushValue(L, cast(ubyte)123); + assert(lua_isnumber(L, -1) && (popValue!ubyte(L) == 123)); + + pushValue(L, cast(short)123); + assert(lua_isnumber(L, -1) && (popValue!short(L) == 123)); + + pushValue(L, 123); + assert(lua_isnumber(L, -1) && (popValue!int(L) == 123)); + + pushValue(L, 123UL); + assert(lua_isnumber(L, -1) && (popValue!ulong(L) == 123)); + + pushValue(L, 1.2f); + assert(lua_isnumber(L, -1) && (popValue!float(L) == 1.2f)); + + pushValue(L, 1.23); + assert(lua_isnumber(L, -1) && (popValue!double(L) == 1.23)); + + //string + string istr = "foobar"; + pushValue(L, istr); + assert(lua_isstring(L, -1) && (popValue!string(L) == "foobar")); + + char[] str = "baz".dup; + pushValue(L, str); + assert(lua_isstring(L, -1) && (popValue!(char[])(L) == "baz")); + + const(char)* cstr = "hi"; + pushValue(L, cstr); + assert(lua_isstring(L, -1) && (strcmp(cstr, popValue!(const(char)*)(L)) == 0)); + + //char + pushValue(L, '\t'); + assert(lua_isstring(L, -1) && getValue!string(L, -1) == "\t"); + assert(popValue!char(L) == '\t'); + + //boolean + pushValue(L, true); + assert(lua_isboolean(L, -1) && (popValue!bool(L) == true)); + + assert(lua_gettop(L) == 0, "bad popValue semantics for primitives"); + + // arrays + static int[] arr = [3, 2, 1]; + pushValue(L, arr); + assert(lua_istable(L, -1) && popValue!(int[])(L) == arr); + + immutable int[] iarr = [1, 2, 3]; + pushValue(L, iarr); + assert(lua_istable(L, -1) && popValue!(typeof(arr))(L) == iarr); + + //void arrays + immutable void[] voidiarr = "foobar"; + pushValue(L, voidiarr); + assert(lua_isstring(L, -1) && popValue!(typeof(voidiarr))(L) == "foobar"); + + void[] voidarr ="baz".dup; + pushValue(L, voidarr); + assert(lua_isstring(L, -1) && popValue!(void[])(L) == "baz"); + + //popStack + extern(C) static int luacfunc(lua_State* L) + { + return 0; + } + + pushValue(L, &luacfunc); + pushValue(L, "test"); + pushValue(L, 123); + pushValue(L, true); + + assert(lua_gettop(L) == 4); + + auto stack = popStack(L, lua_gettop(L)); + assert(lua_gettop(L) == 0); + assert(stack[0].type == LuaType.Function); + assert(stack[1].type == LuaType.String); + assert(stack[2].type == LuaType.Number); + assert(stack[3].type == LuaType.Boolean); +} diff --git a/source/luad/state.d b/source/luad/state.d new file mode 100644 index 0000000..d58757a --- /dev/null +++ b/source/luad/state.d @@ -0,0 +1,581 @@ +module luad.state; + +import std.array, std.range; + +import std.string : toStringz; +import std.typecons : isTuple; + +import luad.c.all; +import luad.stack; +import luad.conversions.classes; + +import luad.base, luad.table, luad.lfunction, luad.dynamic, luad.error; + +/// Specify error handling scheme for $(MREF LuaState.doString) and $(MREF LuaState.doFile). +enum LuaErrorHandler +{ + None, /// No extra error handler. + Traceback /// Append a stack traceback to the error message. +} + +/** + * Represents a Lua state instance. + */ +class LuaState +{ +private: + lua_State* L; // underlying state + LuaTable _G, _R; // global and registry tables + LuaFunction traceback; // debug.traceback, set in openLibs() + bool owner = false; // whether or not to close the underlying state in the finalizer + +public: + /** + * Create a new, empty Lua state. The standard library is not loaded. + * + * If an uncaught error for any operation on this state + * causes a Lua panic for the underlying state, + * an exception of type $(DPREF error, LuaErrorException) is thrown. + * + * See_Also: $(MREF LuaState.openLibs) + */ + this() + { + lua_State* L = luaL_newstate(); + owner = true; + + extern(C) static int panic(lua_State* L) + { + size_t len; + const(char)* cMessage = lua_tolstring(L, -1, &len); + string message = cMessage[0 .. len].idup; + + lua_pop(L, 1); + + throw new LuaErrorException(message); + } + + lua_atpanic(L, &panic); + + this(L); + } + + /** + * Create a D wrapper for an existing Lua state. + * + * The new $(D LuaState) object does not assume ownership of the state. + * Params: + * L = state to wrap + * Note: + * The panic function is not changed - a Lua panic will not throw a D exception! + * See_Also: + $(MREF LuaState.setPanicHandler) + */ + this(lua_State* L) + { + this.L = L; + _G = LuaTable(L, LUA_GLOBALSINDEX); + _R = LuaTable(L, LUA_REGISTRYINDEX); + + lua_pushlightuserdata(L, cast(void*)this); + lua_setfield(L, LUA_REGISTRYINDEX, "__dstate"); + } + + ~this() + { + if(owner) + { + _R.release(); + _G.release(); + traceback.release(); + lua_close(L); + } + else // Unregister state + { + lua_pushnil(L); + lua_setfield(L, LUA_REGISTRYINDEX, "__dstate"); + } + } + + /// The underlying $(D lua_State) pointer for interfacing with C. + @property lua_State* state() nothrow pure @safe + { + return L; + } + + /** + * Get the $(D LuaState) instance for a Lua state. + * Params: + * L = Lua state + * Returns: + * $(D LuaState) for the given $(D lua_State*), or $(D null) if a $(D LuaState) is not currently attached to the state + */ + static LuaState fromPointer(lua_State* L) @trusted + { + lua_getfield(L, LUA_REGISTRYINDEX, "__dstate"); + auto lua = cast(LuaState)lua_touserdata(L, -1); + lua_pop(L, 1); + return lua; + } + + /// Open the standard library. + void openLibs() @trusted + { + luaL_openlibs(L); + traceback = _G.get!LuaFunction("debug", "traceback"); + } + + /// The global table for this instance. + @property LuaTable globals() @trusted + { + return _G; + } + + /// The _registry table for this instance. + @property LuaTable registry() @trusted + { + return _R; + } + + /** + * Set a new panic handler. + * Params: + * onPanic = new panic handler + * Examples: + * ---------------------- + auto L = luaL_newstate(); // found in luad.c.all + auto lua = new LuaState(L); + + static void panic(LuaState lua, in char[] error) + { + throw new LuaErrorException(error.idup); + } + + lua.setPanicHandler(&panic); + * ---------------------- + */ + void setPanicHandler(void function(LuaState, in char[]) onPanic) @trusted + { + extern(C) static int panic(lua_State* L) + { + size_t len; + const(char)* message = lua_tolstring(L, -1, &len); + auto error = message[0 .. len]; + + lua_getfield(L, LUA_REGISTRYINDEX, "__dpanic"); + auto callback = cast(void function(LuaState, in char[]))lua_touserdata(L, -1); + assert(callback); + + scope(exit) lua_pop(L, 2); + + callback(LuaState.fromPointer(L), error); + return 0; + } + + lua_pushlightuserdata(L, onPanic); + lua_setfield(L, LUA_REGISTRYINDEX, "__dpanic"); + + lua_atpanic(L, &panic); + } + + /* + * push debug.traceback error handler to the stack + */ + private void pushErrorHandler() + { + if(traceback.isNil) + throw new Exception("LuaErrorHandler.Traceback requires openLibs()"); + traceback.push(); + } + + /* + * a variant of luaL_do(string|file) with advanced error handling + */ + private void doChunk(alias loader)(in char[] s, LuaErrorHandler handler) + { + if(handler == LuaErrorHandler.Traceback) + pushErrorHandler(); + + if(loader(L, toStringz(s)) || lua_pcall(L, 0, LUA_MULTRET, handler == LuaErrorHandler.Traceback? -2 : 0)) + lua_error(L); + + if(handler == LuaErrorHandler.Traceback) + lua_remove(L, 1); + } + + /** + * Compile a string of Lua _code. + * Params: + * code = _code to compile + * Returns: + * Loaded _code as a function. + */ + LuaFunction loadString(in char[] code) @trusted + { + if(luaL_loadstring(L, toStringz(code)) != 0) + lua_error(L); + + return popValue!LuaFunction(L); + } + + /** + * Compile a file of Lua code. + * Params: + * path = _path to file + * Returns: + * Loaded code as a function. + */ + LuaFunction loadFile(in char[] path) @trusted + { + if(luaL_loadfile(L, toStringz(path)) != 0) + lua_error(L); + + return popValue!LuaFunction(L); + } + + /** + * Execute a string of Lua _code. + * Params: + * code = _code to run + * handler = error handling scheme + * Returns: + * Any _code return values + * See_Also: + * $(MREF LuaErrorHandler) + */ + LuaObject[] doString(in char[] code, LuaErrorHandler handler = LuaErrorHandler.None) @trusted + { + auto top = lua_gettop(L); + + doChunk!(luaL_loadstring)(code, handler); + + auto nret = lua_gettop(L) - top; + + return popStack(L, nret); + } + + /** + * Execute a file of Lua code. + * Params: + * path = _path to file + * handler = error handling scheme + * Returns: + * Any script return values + * See_Also: + * $(MREF LuaErrorHandler) + */ + LuaObject[] doFile(in char[] path, LuaErrorHandler handler = LuaErrorHandler.None) @trusted + { + auto top = lua_gettop(L); + + doChunk!(luaL_loadfile)(path, handler); + + auto nret = lua_gettop(L) - top; + + return popStack(L, nret); + } + + /** + * Create a new, empty table. + * Returns: + * The new table + */ + LuaTable newTable()() @trusted + { + return newTable(0, 0); + } + + /** + * Create a new, empty table with pre-allocated space for members. + * Params: + * narr = number of pre-allocated array slots + * nrec = number of pre-allocated non-array slots + * Returns: + * The new table + */ + LuaTable newTable()(uint narr, uint nrec) @trusted + { + lua_createtable(L, narr, nrec); + return popValue!LuaTable(L); + } + + /** + * Create a new table from an $(D InputRange). + * If the element type of the range is $(D Tuple!(T, U)), + * then each element makes up a key-value pair, where + * $(D T) is the key and $(D U) is the value of the pair. + * For any other element type $(D T), a table with sequential numeric + * keys is created (an array). + * Params: + * range = $(D InputRange) of key-value pairs or elements + * Returns: + * The new table + */ + LuaTable newTable(Range)(Range range) @trusted if(isInputRange!Range) + { + alias ElementType!Range Elem; + + static if(hasLength!Range) + { + immutable numElements = range.length; + assert(numElements < int.max, "lua_createtable only supports int.max many elements"); + } + else + { + immutable numElements = 0; + } + + static if(isTuple!Elem) // Key-value pairs + { + static assert(range.front.length == 2, "key-value tuple must have exactly 2 values."); + + lua_createtable(L, 0, cast(int)numElements); + + foreach(pair; range) + { + pushValue(L, pair[0]); + pushValue(L, pair[1]); + lua_rawset(L, -3); + } + } + else // Sequential table + { + lua_createtable(L, cast(int)numElements, 0); + + int i = 1; + + foreach(value; range) + { + pushValue(L, value); + lua_rawseti(L, -2, i); + ++i; + } + } + + return popValue!LuaTable(L); + } + + /** + * Wrap a D value in a Lua reference. + * + * Note that using this method is only necessary in certain situations, + * such as when you want to act on the reference before fully exposing it to Lua. + * Params: + * T = type of reference. Must be $(D LuaObject), $(D LuaTable), $(D LuaFunction) or $(D LuaDynamic). + * Defaults to $(D LuaObject). + * value = D value to _wrap + * Returns: + * A Lua reference to value + */ + T wrap(T = LuaObject, U)(U value) @trusted if(is(T : LuaObject) || is(T == LuaDynamic)) + { + pushValue(L, value); + return popValue!T(L); + } + + /** + * Register a D class or struct with Lua. + * + * This method exposes a type's constructors and static interface to Lua. + * Params: + * T = class or struct to register + * Returns: + * Reference to the registered type in Lua + */ + LuaObject registerType(T)() @trusted + { + pushStaticTypeInterface!T(L); + return popValue!LuaObject(L); + } + + /** + * Same as calling $(D globals._get) with the same arguments. + * See_Also: + * $(DPREF table, LuaTable._get) + */ + T get(T, U...)(U args) + { + return globals.get!T(args); + } + + /** + * Same as calling $(D globals.get!LuaObject) with the same arguments. + * See_Also: + * $(DPREF table, LuaTable._opIndex) + */ + LuaObject opIndex(T...)(T args) + { + return globals.get!LuaObject(args); + } + + /** + * Same as calling $(D globals._set) with the same arguments. + * See_Also: + * $(DPREF table, LuaTable._set) + */ + void set(T, U)(T key, U value) + { + globals.set(key, value); + } + + /** + * Same as calling $(D globals._opIndexAssign) with the same arguments. + * See_Also: + * $(DPREF table, LuaTable._opIndexAssign) + */ + void opIndexAssign(T, U...)(T value, U args) + { + globals()[args] = value; + } +} + +version(unittest) +{ + import luad.testing; + import std.string : splitLines; + private LuaState lua; +} + +unittest +{ + lua = new LuaState; + assert(LuaState.fromPointer(lua.state) == lua); + + lua.openLibs(); + + //default panic handler + try + { + lua.doString(`error("Hello, D!")`, LuaErrorHandler.Traceback); + assert(false); + } + catch(LuaErrorException e) + { + auto lines = splitLines(e.msg); + assert(lines.length > 1); + assert(lines[0] == `[string "error("Hello, D!")"]:1: Hello, D!`); + } + + lua.set("success", false); + assert(!lua.get!bool("success")); + + lua.doString(`success = true`); + assert(lua.get!bool("success")); + + auto foo = lua.wrap!LuaTable([1, 2, 3]); + foo[4] = "test"; // Lua tables start at 1 + lua["foo"] = foo; + unittest_lua(lua.state, ` + for i = 1, 3 do + assert(foo[i] == i) + end + assert(foo[4] == "test") + `); + + LuaFunction multipleReturns = lua.loadString(`return 1, "two", 3`); + LuaObject[] results = multipleReturns(); + + assert(results.length == 3); + assert(results[0].type == LuaType.Number); + assert(results[1].type == LuaType.String); + assert(results[2].type == LuaType.Number); +} + +unittest // LuaState.newTable(range) +{ + import std.algorithm; + + auto input = [1, 2, 3]; + + lua["tab"] = lua.newTable(input); + + unittest_lua(lua.state, ` + assert(#tab == 3) + for i = 1, 3 do + assert(tab[i] == i) + end + `); + + lua["tab"] = lua.newTable(filter!(i => i == 2)(input)); + + unittest_lua(lua.state, ` + assert(#tab == 1) + assert(tab[1] == 2) + `); + + auto keys = iota(7, 14); + auto values = repeat(42); + + lua["tab"] = lua.newTable(zip(keys, values)); + + unittest_lua(lua.state, ` + assert(not tab[1]) + assert(not tab[6]) + for i = 7, 13 do + assert(tab[i] == 42) + end + assert(not tab[14]) + `); +} + +unittest +{ + static class Test + { + private: + /+ Not working as of 2.062 + static int priv; + static void priv_fun() {} + +/ + + public: + static int pub = 123; + + static string foo() { return "bar"; } + + this(int i) + { + _bar = i; + } + + int bar(){ return _bar; } + int _bar; + } + + lua["Test"] = lua.registerType!Test(); + + unittest_lua(lua.state, ` + assert(type(Test) == "table") + -- TODO: private members are currently pushed too... + --assert(Test.priv == nil) + --assert(Test.priv_fun == nil) + assert(Test._foo == nil) + assert(Test._bar == nil) + + local test = Test(42) + assert(test:bar() == 42) + + assert(Test.pub == 123) + assert(Test.foo() == "bar") + `); +} + +unittest +{ + // setPanicHandler, keep this test last + static void panic(LuaState lua, in char[] error) + { + throw new Exception("hijacked error!"); + } + + lua.setPanicHandler(&panic); + + try + { + lua.doString(`error("test")`); + } + catch(Exception e) + { + assert(e.msg == "hijacked error!"); + } +} diff --git a/source/luad/table.d b/source/luad/table.d new file mode 100644 index 0000000..dbe4802 --- /dev/null +++ b/source/luad/table.d @@ -0,0 +1,349 @@ +module luad.table; + +import luad.c.all; + +import luad.base; +import luad.stack; +import luad.conversions.structs; + +/// Represents a Lua table. +struct LuaTable +{ + /// LuaTable sub-types $(DPREF base, LuaObject) through this reference. + LuaObject object; + + alias object this; + + package this(lua_State* L, int idx) + { + LuaObject.checkType(L, idx, LUA_TTABLE, "LuaTable"); + object = LuaObject(L, idx); + } + + /** + * Lookup a value in this table or in a sub-table of this table. + * Params: + * T = type of value + * args = list of keys, where all keys but the last one should result in a table + * Returns: + * $(D t[k]) where $(D t) is the table for the second-to-last parameter, and $(D k) is the last parameter + * + * Examples: + * ---------------------- + auto execute = lua.get!LuaFunction("os", "execute"); + execute(`echo hello, world!`); + * ---------------------- + */ + T get(T, U...)(U args) @trusted + { + this.push(); + + foreach(key; args) + { + pushValue(this.state, key); + lua_gettable(this.state, -2); + } + + auto ret = getValue!T(this.state, -1); + lua_pop(this.state, args.length + 1); + return ret; + } + + /** + * Read a string value in this table without making a copy of the string. + * The read string is passed to $(D dg), and should not be escaped. + * If the value for $(D key) is not a string, $(D dg) is not called. + * Params: + * key = lookup _key + * dg = delegate to receive string + * Returns: + * $(D true) if the value for $(D key) was a string and passed to $(D dg), $(D false) otherwise + * Examples: + -------------------- + t[2] = "two"; + t.readString(2, str => assert(str == "two")); + -------------------- + */ + bool readString(T)(T key, scope void delegate(in char[] str) dg) @trusted + { + this.push(); + scope(exit) lua_pop(this.state, 1); + + pushValue(this.state, key); + + lua_gettable(this.state, -2); + scope(exit) lua_pop(this.state, 1); + + if(lua_isstring(this.state, -1) == 0) + return false; + + size_t len; + const(char)* cstr = lua_tolstring(this.state, -1, &len); + + dg(cstr[0 .. len]); + return true; + } + + /** + * Same as calling $(D get!LuaObject) with the same arguments. + * Examples: + * --------------------- + auto luapath = lua["package", "path"]; + writefln("LUA_PATH:\n%s", luapath); + * --------------------- + * See_Also: + * $(MREF LuaTable.get) + */ + LuaObject opIndex(T...)(T args) + { + return get!LuaObject(args); + } + + /** + * Set a key-value pair in this table. + * Params: + * key = key to _set + * value = value for $(D key) + */ + void set(T, U)(T key, U value) @trusted + { + this.push(); + scope(success) lua_pop(this.state, 1); + + pushValue(this.state, key); + pushValue(this.state, value); + lua_settable(this.state, -3); + } + + /** + * Set a key-value pair this table or in a sub-table of this table. + * Params: + * value = value to set + * args = list of keys, where all keys but the last one should result in a table + * Returns: + * $(D t[k] = value), where $(D t) is the table for the second-to-last parameter in args, + * and $(D k) is the last parameter in args + * + * Examples: + * ---------------------- + lua["string", "empty"] = (in char[] s){ return s.length == 0; }; + lua.doString(`assert(string.empty(""))`); + * ---------------------- + */ + void opIndexAssign(T, U...)(T value, U args) @trusted + { + this.push(); + scope(success) lua_pop(this.state, 1); + + foreach(i, arg; args) + { + static if(i != args.length - 1) + { + pushValue(this.state, arg); + lua_gettable(this.state, -2); + } + } + + pushValue(this.state, args[$-1]); + pushValue(this.state, value); + lua_settable(this.state, -3); + + lua_pop(this.state, args.length - 1); + } + + /** + * Create struct of type $(D T) and fill its members with fields from this table. + * + * Struct fields that are not present in this table are left at their default value. + * + * Params: + * T = any struct type + * + * Returns: + * Newly created struct + */ + T toStruct(T)() @trusted if (is(T == struct)) + { + push(); + return popValue!T(this.state); + } + + /** + * Fill a struct's members with fields from this table. + * Params: + * s = struct to fill + */ + void copyTo(T)(ref T s) @trusted if (is(T == struct)) + { + push(); + fillStruct(this.state, -1, s); + lua_pop(L, 1); + } + + /** + * Set the metatable for this table. + * Params: + * meta = new metatable + */ + void setMetaTable(ref LuaTable meta) @trusted + in{ assert(this.state == meta.state); } + body + { + this.push(); + meta.push(); + lua_setmetatable(this.state, -2); + lua_pop(this.state, 1); + } + + /** + * Get the metatable for this table. + * Returns: + * A reference to the metatable for this table. The reference is nil if this table has no metatable. + */ + LuaTable getMetaTable() @trusted + { + this.push(); + scope(success) lua_pop(this.state, 1); + + return lua_getmetatable(this.state, -1) == 0? LuaTable() : popValue!LuaTable(this.state); + } + + /** + * Get the array length of the table. + */ + size_t length() @trusted + { + this.push(); + size_t len = lua_objlen(this.state, -1); + lua_pop(this.state, 1); + return len; + } + + /** + * Iterate over the values in this table. + */ + int opApply(T)(int delegate(ref T value) dg) @trusted + { + this.push(); + lua_pushnil(this.state); + while(lua_next(this.state, -2) != 0) + { + auto value = popValue!T(this.state); + int result = dg(value); + if(result != 0) + { + lua_pop(this.state, 2); + return result; + } + } + lua_pop(this.state, 1); + return 0; + } + + /** + * Iterate over the key-value pairs in this table. + */ + int opApply(T, U)(int delegate(ref U key, ref T value) dg) @trusted + { + this.push(); + lua_pushnil(this.state); + while(lua_next(this.state, -2) != 0) + { + auto value = popValue!T(this.state); + auto key = getValue!U(this.state, -1); + + int result = dg(key, value); + if(result != 0) + { + lua_pop(this.state, 2); + return result; + } + } + lua_pop(this.state, 1); + return 0; + } +} + +unittest +{ + lua_State* L = luaL_newstate(); + scope(success) + { + assert(lua_gettop(L) == 0); + lua_close(L); + } + + lua_newtable(L); + auto t = popValue!LuaTable(L); + + assert(t.type == LuaType.Table); + + t.set("foo", "bar"); + assert(t.get!string("foo") == "bar"); + + t.set("foo", nil); + assert(t.get!LuaObject("foo").isNil); + + t.set("foo", ["outer": ["inner": "hi!"]]); + auto s = t.get!(string)("foo", "outer", "inner"); + assert(s == "hi!"); + + auto o = t["foo", "outer"]; + assert(o.type == LuaType.Table); + + t["foo", "outer", "inner"] = "hello!"; + auto s2 = t.get!(string)("foo", "outer", "inner"); + assert(s2 == "hello!"); + + // length + t.set("array", ["one", "two"]); + auto a = t.get!LuaTable("array"); + assert(a.length == 2); + + // readString + t[2] = "two"; + bool success = t.readString(2, (in char[] str) { + assert(str == "two"); + }); + assert(success); + + t[2] = true; + success = t.readString(2, (in char[] str) { assert(false); }); + assert(!success); + + // metatable + pushValue(L, ["__index": (LuaObject self, string key){ + return key; + }]); + auto meta = popValue!LuaTable(L); + + lua_newtable(L); + auto t2 = popValue!LuaTable(L); + + t2.setMetaTable(meta); + + auto test = t2.get!string("foobar"); + assert(test == "foobar"); + + assert(t2.getMetaTable() == meta); + + // opApply + auto input = [1, 2, 3]; + pushValue(L, input); + auto applyTest = popValue!LuaTable(L); + + int i = 0; + foreach(int v; applyTest) + { + assert(input[i++] == v); + } + + auto inputWithKeys = ["one": 1, "two": 2, "three": 3]; + pushValue(L, inputWithKeys); + auto applyTestKeys = popValue!LuaTable(L); + + foreach(string key, int value; applyTestKeys) + { + assert(inputWithKeys[key] == value); + } +} diff --git a/source/luad/testing.d b/source/luad/testing.d new file mode 100644 index 0000000..39bb026 --- /dev/null +++ b/source/luad/testing.d @@ -0,0 +1,27 @@ +/// Module used internally by the unittest code. +module luad.testing; + +import luad.c.all; + +import core.stdc.string : strcmp; +import std.string : format; +import std.string : toStringz; + +/** Test a piece of Lua code. + * Params: + * L = Lua state to run in. + * code = Lua code. + */ +void unittest_lua(lua_State* L, string code, string chunkName = __FILE__, uint chunkLocation = __LINE__) +{ + chunkName = format("@%s script on line %d", chunkName, chunkLocation); + if(luaL_loadbuffer(L, code.ptr, code.length, toStringz(chunkName)) != 0) + lua_error(L); + + lua_call(L, 0, 0); +} + +/** Main function stub for unittest build. */ +version(luad_unittest_main) void main() +{ +} \ No newline at end of file diff --git a/source/lunch/color.d b/source/lunch/color.d new file mode 100644 index 0000000..51eed05 --- /dev/null +++ b/source/lunch/color.d @@ -0,0 +1,97 @@ +module lunch.color; + + +const(char)[] black(const(char)[] str) +{ + return "\x1B[30m" ~ str ~ "\x1B[0m"; +} + +const(char)[] red(const(char)[] str) +{ + return "\x1B[31m" ~ str ~ "\x1B[0m"; +} + +const(char)[] green(const(char)[] str) +{ + return "\x1B[32m" ~ str ~ "\x1B[0m"; +} + +const(char)[] yellow(const(char)[] str) +{ + return "\x1B[33m" ~ str ~ "\x1B[0m"; +} + +const(char)[] blue(const(char)[] str) +{ + return "\x1B[34m" ~ str ~ "\x1B[0m"; +} + +const(char)[] magenta(const(char)[] str) +{ + return "\x1B[35m" ~ str ~ "\x1B[0m"; +} + +const(char)[] cyan(const(char)[] str) +{ + return "\x1B[36m" ~ str ~ "\x1B[0m"; +} + +const(char)[] white(const(char)[] str) +{ + return "\x1B[37m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightBlack(const(char)[] str) +{ + return "\x1B[90m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightRed(const(char)[] str) +{ + return "\x1B[91m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightGreen(const(char)[] str) +{ + return "\x1B[92m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightYellow(const(char)[] str) +{ + return "\x1B[93m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightBlue(const(char)[] str) +{ + return "\x1B[94m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightMagenta(const(char)[] str) +{ + return "\x1B[95m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightCyan(const(char)[] str) +{ + return "\x1B[96m" ~ str ~ "\x1B[0m"; +} + +const(char)[] brightWhite(const(char)[] str) +{ + return "\x1B[97m" ~ str ~ "\x1B[0m"; +} + + +shared static this() +{ + version (Windows) + { + import core.stdc.stdlib; + import core.sys.windows.windows; + + // Are we attached to console? + if (GetConsoleWindow()) + // Then run `color` to enable colors :) + system("color"); + } +} diff --git a/source/lunch/conf.d b/source/lunch/conf.d new file mode 100644 index 0000000..9f3146f --- /dev/null +++ b/source/lunch/conf.d @@ -0,0 +1,158 @@ +module lunch.conf; + +import toml; + +import std.conv; +import std.traits; + + +private struct Name +{ + string str; + string toString() { return str; } +} + + +struct AppConfig +{ + bool talkative; + bool report_errors; + string report_url; + string config_name; + bool load_config; + bool auto_launch; + bool auto_update; + bool check_update; +} + +struct UIConfig +{ + bool enabled; + bool launch; + bool update; + bool config_dump; + bool exit; + string message; + string launch_label; + string update_label; + string update_avail_label; + string config_dump_label; + string exit_label; +} + +struct LaunchConfig +{ + string[] command; + string workdir; + bool use_script; + string entry_file; + string source_dir; + +version (Windows): + bool hide_when_running; +} + +struct UpdateConfig +{ + string seedurl; + string workdir; + size_t parallel_downloads; + string[] exclude; +} + +struct Config +{ + @Name("application") + AppConfig app; + @Name("interface") + UIConfig ui; + LaunchConfig launcher; + UpdateConfig updater; +} + + +immutable string default_config_toml = import("config.toml"); +immutable Config default_config; +immutable Config config; + + +private string dash2minus(string str) +{ + string newStr = ""; + foreach (c; str) + { + if (c == '_') + newStr ~= '-'; + else + newStr ~= c; + } + return newStr; +} + + +void wrapTOML(T)(ref T config, TOMLValue[string] toml, bool ignore_missing = false) @safe +{ + static foreach (name; __traits(allMembers, T)) + {{ + alias member = __traits(getMember, config, name); + alias type = typeof(__traits(getMember, T, name)); + type* field = &__traits(getMember, config, name); + + static if (hasUDA!(member, Name)) + enum key = getUDAs!(member, Name)[0].str; + else + enum key = name.dash2minus; + + TOMLValue* value = key in toml; + if (!value) + { + if (!ignore_missing) + throw new Exception("Missing field \""~key~"\" of type "~type.stringof); + } + else + { + static if (isSomeString!type) + { + *field = value.str.to!type; + } + else static if (is(type == string[])) + { + *field = []; + foreach (_, entry; value.array) + *field ~= entry.str; + } + else static if (is(type == bool)) + { + *field = value.boolean; + } + else static if (isIntegral!type) + { + *field = value.integer.to!type; + } + else static if (isFloatingPoint!type) + { + *field = value.floating.to!type; + } + else + { + wrapTOML(*field, value.table, ignore_missing); + } + } + }} +} + + +Config parseConfig(string toml) @safe +{ + Config config; + TOMLDocument doc = parseTOML(toml); + wrapTOML(config, doc); + return config; +} + + +shared static this() +{ + default_config = cast(immutable)parseConfig(default_config_toml); + config = default_config; +} diff --git a/source/lunch/http.d b/source/lunch/http.d new file mode 100644 index 0000000..f892b96 --- /dev/null +++ b/source/lunch/http.d @@ -0,0 +1,114 @@ +module lunch.http; + +import std.stdio; +import std.file; +import std.traits; +import std.string; +import std.net.curl : + c_get = get, + c_post = post, + c_put = put, + HTTP, + CurlException, + AutoProtocol; +import core.thread; +import lunch.logger; + + + +private ReturnType!fun _retry(alias fun)(Parameters!fun args) +{ + CurlException last_ex; + for (int n = 0; n < 10; n++) + { + try + return fun(args); + catch (CurlException ex) + last_ex = ex; + Thread.sleep(dur!"msecs"(500)); + } + throw last_ex; +} + + +private const(char)[] _sanitize(const(char)[] url) +{ + return url.replace(" ", "%20"); +} + + +T[] get(Conn = AutoProtocol, T = char)(const(char)[] url, Conn conn = Conn()) +{ + try + { + T[] res = _retry!(c_get!(Conn, T))(_sanitize(url), conn); + infof("GET %s", url); + return res; + } + catch (CurlException ex) + { + erroref("GET %s", ex, url); + assert(0); + } +} + +T[] post(T = char, PostUnit)(const(char)[] url, const(PostUnit)[] postData, HTTP conn = HTTP()) +{ + try + { + T[] res = _retry!(c_post!(T, PostUnit))(_sanitize(url), postData, conn); + infof("POST %s", url); + return res; + } + catch (CurlException ex) + { + erroref("POST %s", ex, url); + assert(0); + } +} + +T[] put(Conn = AutoProtocol, T = char, PutUnit)(const(char)[] url, const(PutUnit)[] putData, Conn conn = Conn()) +{ + try + { + T[] res = _retry!(c_put!(Conn, T, PutUnit))(_sanitize(url), putData, conn); + infof("PUT %s", url); + return res; + } + catch (CurlException ex) + { + erroref("PUT %s", ex, url); + assert(0); + } +} + +private void _download(const(char)[] url, string file) +{ + scope (failure) + if (exists(file)) + remove(file); + + File handle = File(file, "wb"); + + HTTP http = HTTP(_sanitize(url)); + http.onReceive = (ubyte[] data) + { + handle.rawWrite(data); + return data.length; + }; + http.perform(); +} + +void download(const(char)[] url, string file) +{ + try + { + _retry!_download(url, file); + infof("DL %s", url); + } + catch (CurlException ex) + { + erroref("DL %s", cast(Exception)ex, url); + assert(0); + } +} diff --git a/source/lunch/launch.d b/source/lunch/launch.d new file mode 100644 index 0000000..8c7c424 --- /dev/null +++ b/source/lunch/launch.d @@ -0,0 +1,86 @@ +module lunch.launch; + +import std.file; +import std.path; +import std.array; +import std.process; +import luad.all; +import lunch.conf; +import lunch.logger; + +version (Windows) +{ + import core.sys.windows.windows; +} + + +void launch() +{ + string old_path = getcwd(); + scope (exit) chdir(old_path); + + version (Windows) + { + HWND hConsole = GetConsoleWindow(); + if (config.launcher.hide_when_running) + ShowWindow(hConsole, SW_HIDE); + + scope (exit) + if (config.launcher.hide_when_running) + ShowWindow(hConsole, SW_SHOW); + } + + if (!exists(config.launcher.workdir)) + error("Launcher workdir does not exist"); + + if (config.launcher.use_script) + { + if (!exists(config.launcher.source_dir)) + error("Lua source dir does not exist"); + + string source_dir = absolutePath(config.launcher.source_dir); + auto lua_root = (string path) => chainPath(source_dir, path).array; + + if (!exists(lua_root(config.launcher.entry_file))) + error("Lua entry file is missing"); + + auto lua = new LuaState; + lua.openLibs(); + + auto orig_require = lua["require"].to!(LuaObject delegate(string mod)); + lua["require"] = (string mod) + { + auto work_dir = getcwd(); + chdir(source_dir); + + auto res = orig_require(mod); + + chdir(work_dir); + return res; + }; + + chdir(config.launcher.workdir); + try + { + lua.doFile(lua_root(config.launcher.entry_file)); + } + catch (Exception ex) + { + errore("Lua script failed", ex); + } + } + else + { + info("Launching"); + try + { + chdir(config.launcher.workdir); + Pid pid = spawnProcess(config.launcher.command); + wait(pid); + } + catch (Exception ex) + { + errore("Failed to launch application", ex); + } + } +} diff --git a/source/lunch/logger.d b/source/lunch/logger.d new file mode 100644 index 0000000..6d86c58 --- /dev/null +++ b/source/lunch/logger.d @@ -0,0 +1,84 @@ +module lunch.logger; + +import std.stdio; +import std.format; +import lunch.conf; + + +private shared string _log; + +void _writefln(Char, Args...)(string file, size_t line, Char[] fmt, Args args) @trusted +{ + synchronized + { + _log ~= format("%s:%d ", file, line) ~ format(fmt, args) ~ '\n'; + if (config.app.talkative) + writefln(fmt, args); + } +} + +string log() @trusted +{ + return _log; +} + + +void infof(Char, Args...)(Char[] fmt, Args args, string file = __FILE__, size_t line = __LINE__) @safe +{ + _writefln(file, line, format("[INFO] %s", fmt), args); +} + +void info(Char)(Char[] msg, string file = __FILE__, size_t line = __LINE__) @safe +{ + infof!(immutable char, Char[])("%s", msg, file, line); +} + + +void warnf(Char, Args...)(Char[] fmt, Args args, string file = __FILE__, size_t line = __LINE__) @safe +{ + _writefln(file, line, format("[WARN] %s", fmt), args); +} + +void warn(Char)(Char[] msg, string file = __FILE__, size_t line = __LINE__) @safe +{ + warnf!(immutable char, Char[])("%s", msg, file, line); +} + + +void warnef(Char, Args...)(Char[] fmt, Exception ex, Args args, string file = __FILE__, size_t line = __LINE__) @safe +{ + _writefln(file, line, format("[WARN] %s", fmt), args); + _writefln(file, line, "[<==>] %s", ex); +} + +void warne(Char)(Char[] msg, Exception ex, string file = __FILE__, size_t line = __LINE__) @safe +{ + warnef!(immutable char, Char[])("%s", ex, msg, file, line); +} + + +void errorf(E = Exception, Char, Args...)(Char[] fmt, Args args, string file = __FILE__, size_t line = __LINE__) @trusted +{ + _writefln(file, line, format("[ERRO] %s", fmt), args); + E ex = new E(format(fmt, args), file, line); + _writefln(file, line, "[<==>] %s", ex); + throw ex; +} + +void error(E = Exception, Char)(Char[] msg, string file = __FILE__, size_t line = __LINE__) @safe +{ + errorf!(E, immutable char, Char[])("%s", msg, file, line); +} + + +void erroref(Char, Args...)(Char[] fmt, Exception ex, Args args, string file = __FILE__, size_t line = __LINE__) @safe +{ + _writefln(file, line, format("[ERRO] %s", fmt), args); + _writefln(file, line, "[<==>] %s", ex); + throw ex; +} + +void errore(Char)(Char[] msg, Exception ex, string file = __FILE__, size_t line = __LINE__) @safe +{ + erroref!(immutable char, Char[])("%s", ex, msg, file, line); +} diff --git a/source/lunch/main.d b/source/lunch/main.d new file mode 100644 index 0000000..89c1a2b --- /dev/null +++ b/source/lunch/main.d @@ -0,0 +1,128 @@ +module lunch.main; + +import std.stdio; +import std.conv; +import std.path; +import std.file : readText, writeFile = write, exists, chdir, thisExePath; +import std.string; +import toml; +import lunch.conf; +import lunch.http; +import lunch.color; +import lunch.logger; +import lunch.update; +import lunch.launch;; + + +void app() +{ + // Focus on exe + chdir( thisExePath.dirName() ); + + // Dynamicly load the config. + if (config.app.load_config && exists(config.app.config_name)) + try + { + info("Loading external configuration"); + wrapTOML(cast()config, readText(config.app.config_name).parseTOML(), true); + } + catch (Exception e) + warne("Failed loading external configuration", e); + + // Auto update + if (config.app.auto_update) + update(); + + // Auto launch + if (config.app.auto_launch) + launch(); + + // Show UI + bool exit_ui = false; + while (config.ui.enabled && !exit_ui) + { + void delegate()[] options; + + writeln("\x1B[3J\x1B[1;1H"); + writeln(config.ui.message); + writeln(); + + if (config.ui.launch) + { + options ~= () { launch(); }; + writefln("[%d] %s", options.length, config.ui.launch_label); + } + + if (config.ui.update) + { + options ~= () { update(); }; + if (config.app.check_update && updateAvailable()) + writefln("[%d] %s", options.length, config.ui.update_avail_label); + else + writefln("[%d] %s", options.length, config.ui.update_label); + } + + if (config.ui.config_dump) + { + options ~= () { writeFile(config.app.config_name, default_config_toml); }; + writefln("[%d] %s", options.length, config.ui.config_dump_label); + } + + if (config.ui.exit) + { + options ~= () { exit_ui = true; }; + writefln("[%d] %s", options.length, config.ui.exit_label); + } + + int opt; + try + { + writef("\nSelect 1-%d : ", options.length); + opt = readln().strip().to!int - 1; + } + catch (Exception ex) + { + continue; + } + + if (opt >= 0 && opt < options.length) + options[opt](); + } + + info("Exit"); +} + + +void main() +{ + try + { + app(); + } + catch (Exception ex) + { + debug + { + writefln("\x1B[31m%s\x1B[0m", ex); + } + else + { + writeln("Critical error".red, ": ", ex.message.yellow); + + if (config.app.report_errors) + { + try + { + writefln("Log reported to: %s", put(config.app.report_url, log).cyan); + } + catch (Exception) { } + } + + version (Windows) + { + writeln("\nPress enter to exit..."); + readln(); + } + } + } +} diff --git a/source/lunch/ui.d b/source/lunch/ui.d new file mode 100644 index 0000000..6af0158 --- /dev/null +++ b/source/lunch/ui.d @@ -0,0 +1 @@ +module lunch.ui; diff --git a/source/lunch/update.d b/source/lunch/update.d new file mode 100644 index 0000000..3b41d07 --- /dev/null +++ b/source/lunch/update.d @@ -0,0 +1,419 @@ +module lunch.update; + +import std.datetime; +import std.stdio : writefln, File; +import std.traits; +import std.json; +import std.conv; +import std.file; +import std.path; +import std.file; +import std.math; +import std.string; +import std.digest.sha; +import std.array; +import std.algorithm; +import std.parallelism; +import lunch.conf; +import lunch.http; +import lunch.logger; + + +private struct RemoteFile +{ + string file; + string source; + string hash; + ulong size; + size_t mtime; +} + +private struct Remote +{ + string source; + ulong size; + size_t mtime; + RemoteFile[] files; +} + +private struct LocalFile +{ + string file; + ulong size; + size_t mtime; + + string hash() inout @property + { + if (_hash) + return _hash; + + synchronized + { + auto path = chainPath(config.updater.workdir, file).array; + auto file = File(path, "rb"); + auto result = digest!SHA256(file.byChunk(4096 * 1024)); + cast()_hash = result.toHexString().toLower.idup; + } + + return _hash; + } + + private string _hash = null; +} + +private struct Local +{ + ulong size; + size_t mtime; + LocalFile[] files; +} + +private struct Action +{ + enum What + { + remove, + download, + } + + What what; + string file; + string url; + + alias this = What; +} + +private struct Actions +{ + Action[] actions; + + alias this = actions; +} + +private bool _remote_set = false; +private immutable(Remote) _remote; + +private bool _local_set = false; +private immutable(Local) _local; + +private bool _actions_set = false; +private immutable(Actions) _actions; + + +private JSONValue[string] safe_object(JSONValue value) @trusted +{ + if (value.type != JSONType.object) + errorf("JSON format error, object expected got %s", value.type); + return value.object; +} + +private JSONValue[] safe_array(JSONValue value) @trusted +{ + if (value.type != JSONType.array) + errorf("JSON format error, array expected got %s", value.type); + return value.array; +} + +private T safe_get(T)(JSONValue value) @trusted +{ + static if (!isBasicType!T && !isSomeString!T) + static assert(0, "Only basic types and strings are supported"); + final switch (value.type) + { + case JSONType.array: + error("Arrays are not supported"); + break; + case JSONType.false_: + static if (isBoolean!T) + return false; + else + errorf("Can't map boolean to %s", typeid(T)); + break; + case JSONType.float_: + static if (isFloatingPoint!T) + return value.get!T; + else + errorf("Can't map float to %s", typeid(T)); + break; + case JSONType.integer: + static if (isIntegral!T && isSigned!T) + return value.get!T; + else static if (isIntegral!T && isUnsigned!T) + return value.get!(Signed!T).to!T; + else + errorf("Can't map integer to %s", typeid(T)); + break; + case JSONType.null_: + error("Null references are not supported"); + break; + case JSONType.object: + error("Objects are not supported"); + break; + case JSONType.string: + static if (isSomeString!T) + return value.get!T; + else + errorf("Can't map string to %s", typeid(T)); + break; + case JSONType.true_: + static if (isBoolean!T) + return true; + else + errorf("Can't map boolean to %s", typeid(T)); + break; + case JSONType.uinteger: + static if (isIntegral!T && isUnsigned!T) + return value.get!T; + else + errorf("Can't map uinteger to %s", typeid(T)); + } + assert(0); +} + +void wrapJSON(T)(ref T wrapper, JSONValue[string] json, bool ignore_missing = false) @safe +{ + static foreach (name; __traits(allMembers, T)) + {{ + alias member = __traits(getMember, wrapper, name); + alias type = typeof(__traits(getMember, T, name)); + type* field = &__traits(getMember, wrapper, name); + + enum key = name; + + JSONValue* value = key in json; + if (!value) + { + if (!ignore_missing) + error("Missing field \""~key~"\" of type "~type.stringof); + } + else + { + static if (isBasicType!type || isSomeString!type) + { + *field = safe_get!type(*value); + } + else static if (isArray!type) + { + alias el_type = ForeachType!type; + static if (isBasicType!el_type) + { + *field = []; + foreach (_, entry; value.safe_array) + *field ~= entry.get!el_type; + } + else + { + *field = []; + foreach (_, entry; safe_array(*value)) + { + el_type el; + wrapJSON(el, safe_object(entry)); + *field ~= el; + } + } + } + else + { + wrapJSON(*field, safe_object(value), ignore_missing); + } + } + }} +} + + +private string workdir(string path) +{ + return chainPath(config.updater.workdir, path).array; +} + + +private immutable(Remote) remote() +{ + if (_remote_set) + return _remote; + + info("Fetching seed"); + char[] seed_json; + try + seed_json = get(config.updater.seedurl); + catch (Exception ex) + errore("Failed to fetch seed", ex); + if (!seed_json) + error("Failed fetching seed : %s", config.updater.seedurl); + + info("Parsing seed"); + Remote rem; + try + wrapJSON(rem, parseJSON(seed_json).safe_object); + catch (Exception ex) + errore("Received malformed seed data", ex); + cast()_remote = rem; + _remote_set = true; + + return _remote; +} + + +private immutable(Local) local() +{ + if (_local_set) + return _local; + + info("Scanning files"); + Local loc; + + string workdir = absolutePath(config.updater.workdir); + + if (!workdir.exists) + return Local(); + + if (!workdir.isDir) + errorf("\"%s\" exists and is not a directory", workdir); + + foreach (entry; dirEntries(workdir, SpanMode.breadth)) + { + if (!entry.isFile) + continue; + + loc.files ~= LocalFile( + file: entry.name.relativePath(workdir).replace('\\', '/'), + size: entry.size.to!uint, + mtime: entry.timeLastModified.toUnixTime, + ); + + loc.size += entry.size; + } + + loc.mtime = loc.files.map!"a.mtime".maxElement(0); + + cast()_local = loc; + _local_set = true; + + return _local; +} + + +private immutable(Actions) actions() +{ + if (_actions_set) + return _actions; + + info("Checking for updates"); + + RemoteFile[string] rem; + foreach (file; remote.files) + rem[file.file] = file; + + LocalFile[string] loc; + foreach (file; local.files) + loc[file.file] = file; + + Actions act; + + auto exclude = (string file) => config.updater.exclude.map!( + pat => globMatch(file, pat) + ).any; + + bool[string] to_be_deleted; + foreach (file; loc.byKey) + if ( !exclude(file) ) + to_be_deleted[file] = true; + + SysTime now = Clock.currTime(); + foreach (this_rem; rem.byValue) + { + if ( exclude(this_rem.file) ) + continue; + + auto this_act = Action( + Action.download, + workdir(this_rem.file), + this_rem.source + ); + + auto this_loc = this_rem.file in loc; + + if (!this_loc) + { + act ~= this_act; + continue; + } + + to_be_deleted.remove(this_loc.file); + + if ( + (this_loc.mtime < this_rem.mtime) && + (this_loc.hash != this_rem.hash) + ){ + act ~= this_act; + continue; + } + else + { + workdir(this_loc.file).setTimes(now, now); + } + } + + foreach (file; to_be_deleted.byKey) + act ~= Action(Action.remove, workdir(file), ""); + + cast()_actions = act; + _actions_set = true; + + if (_actions.length == 0) + info("Already up to date"); + else + info("Update available"); + + return _actions; +} + + +public bool updateAvailable() +{ + if (actions.length != 0) + return true; + else + return false; +} + +public void update() +{ + info("Updating"); + + scope (exit) cast() _actions = []; + + const dl_total = actions.actions.count!"a.what == b"(Action.download); + const dl_pad = cast(int)log10(cast(float)dl_total) + 1; + size_t dl_count = 0; + + const old_defaultpool = defaultPoolThreads; + scope (exit) defaultPoolThreads = old_defaultpool; + defaultPoolThreads = config.updater.parallel_downloads.to!uint - 1; + + foreach (action; parallel(actions.actions, 1)) + final switch(action.what) + { + case Action.remove: + remove(action.file); + break; + case Action.download: + mkdirRecurse(dirName(action.file)); + synchronized + { + dl_count += 1; + writefln("[%*d|%*d] %s", dl_pad, dl_count, dl_pad, dl_total, action.file); + } + download(action.url, action.file); + break; + } + + foreach (ent; dirEntries(config.updater.workdir, SpanMode.depth)) + { + if (!ent.isDir) + continue; + + if (dirEntries(ent, SpanMode.shallow).empty) + rmdir(ent); + } +} diff --git a/source/toml/LICENSE b/source/toml/LICENSE new file mode 100644 index 0000000..4b10b3f --- /dev/null +++ b/source/toml/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Kripth + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/source/toml/datetime.d b/source/toml/datetime.d new file mode 100644 index 0000000..8b9f4fd --- /dev/null +++ b/source/toml/datetime.d @@ -0,0 +1,74 @@ +// Written in the D programming language. + +/** + * + * Custom types for TOML's datetimes that add fractional time to D ones. + * + * License: $(HTTP https://github.com/Kripth/toml/blob/master/LICENSE, MIT) + * Authors: Kripth + * References: $(LINK https://github.com/toml-lang/toml/blob/master/README.md) + * Source: $(HTTP https://github.com/Kripth/toml/blob/master/src/toml/datetime.d, toml/_datetime.d) + * + */ +module toml.datetime; + +import std.conv : to; +import std.datetime : Duration, dur, DateTimeD = DateTime, Date, TimeOfDayD = TimeOfDay; + +struct DateTime { + + public Date date; + public TimeOfDay timeOfDay; + +@safe: + + public pure inout @property DateTimeD dateTime() { + return DateTimeD(this.date, this.timeOfDay.timeOfDay); + } + + alias dateTime this; + + public static pure DateTime fromISOExtString(scope const(char)[] str) { + Duration frac; + if (str.length > 19 && str[19] == '.') { + frac = dur!"msecs"(to!ulong(str[20 .. $])); + str = str[0 .. 19]; + } + auto dt = DateTimeD.fromISOExtString(str); + return DateTime(dt.date, TimeOfDay(dt.timeOfDay, frac)); + } + + public pure inout string toISOExtString() scope { + return this.date.toISOExtString() ~ "T" ~ this.timeOfDay.toString(); + } + +} + +struct TimeOfDay { + + public TimeOfDayD timeOfDay; + public Duration fracSecs; + +@safe: + + alias timeOfDay this; + + public static pure TimeOfDay fromISOExtString(scope const(char)[] str) { + Duration frac; + if (str.length > 8 && str[8] == '.') { + frac = dur!"msecs"(to!ulong(str[9 .. $])); + str = str[0 .. 8]; + } + return TimeOfDay(TimeOfDayD.fromISOExtString(str), frac); + } + + public pure inout string toISOExtString() scope { + immutable msecs = this.fracSecs.total!"msecs"; + if (msecs != 0) { + return this.timeOfDay.toISOExtString() ~ "." ~ to!string(msecs); + } else { + return this.timeOfDay.toISOExtString(); + } + } + +} diff --git a/source/toml/package.d b/source/toml/package.d new file mode 100644 index 0000000..d0adc5f --- /dev/null +++ b/source/toml/package.d @@ -0,0 +1,18 @@ +// Written in the D programming language. + +/** + * + * Tom's Obvious, Minimal Language (v1.0.0). + * + * License: $(HTTP https://github.com/Kripth/toml/blob/master/LICENSE, MIT) + * Authors: Kripth + * References: $(LINK https://github.com/toml-lang/toml/blob/master/README.md) + * Source: $(HTTP https://github.com/Kripth/toml/blob/master/src/toml/package.d, toml/_package.d) + * + */ +module toml; + +public import std.datetime : SysTime, Date; + +public import toml.datetime : DateTime, TimeOfDay; +public import toml.toml : TOMLOptions, TOMLType, TOML_TYPE, TOMLDocument, TOMLValue, parseTOML, TOMLException, TOMLParserException; diff --git a/source/toml/serialize.d b/source/toml/serialize.d new file mode 100644 index 0000000..4e54135 --- /dev/null +++ b/source/toml/serialize.d @@ -0,0 +1,294 @@ +module toml.serialize; + +import toml.toml; + +import std.array; +import std.traits; + +static if (__VERSION__ >= 2097) +{ + import std.sumtype; + private enum hasSumType = true; +} +else +{ + private struct SumType(Types...) + { + } + private enum hasSumType = false; +} + +// UDAs: +struct tomlName { + string name; +} + +enum tomlIgnored; +// --- + +string serializeTOML(T)(T value) @safe { + auto ret = appender!string; + serializeTOML(value, ret); + return ret.data; +} + +void serializeTOML(T, Output)(T value, ref Output output) @safe { + serializeTOML(value, output, "", ""); +} + +private: + +// indentation increase per level +enum oneIndentLevel = " "; + +template fieldName(alias field) { + enum nameUDAs = getUDAs!(field, tomlName); + static if (nameUDAs.length == 1) + enum fieldName = nameUDAs[0].name; + else static if (nameUDAs.length == 0) + enum fieldName = __traits(identifier, field); + else + static assert(false, "Field " ~ __traits(identifier, field) ~ " has multiple @tomlName UDAs"); +} + +void serializeTOML(T, Output)(T value, ref Output output, string indent, string group) +@safe +if (isPlainStruct!T && !is(T == MapT[string], MapT) && !is(T == SumType!Types, Types...)) { + foreach (i, ref v; value.tupleof) { + { + static if (isValueSerializable!(typeof(v)) && getUDAs!(value.tupleof[i], tomlIgnored).length == 0 && !isStructArray!(typeof(v))) { + enum prefix = fieldName!(value.tupleof[i]) ~ " = "; + if (indent.length) + output.put(indent); + output.put(prefix); + serializeTOMLValue(v, output); + output.put("\n"); + } + } + } + + foreach (i, ref v; value.tupleof) { + { + static if (isValueSerializable!(typeof(v)) && getUDAs!(value.tupleof[i], tomlIgnored).length == 0 && isStructArray!(typeof(v))) { + enum prefix = fieldName!(value.tupleof[i]) ~ "]]\n"; + auto deeperIndent = v.length ? indent ~ oneIndentLevel : null; + auto deepGroup = group ~ (fieldName!(value.tupleof[i]) ~ "."); + foreach (item; v) { + output.put("\n"); + if (indent.length) + output.put(indent); + output.put("[["); + if (group.length) + output.put(group); + output.put(prefix); + serializeTOML(item, output, deeperIndent, deepGroup); + } + } + } + } + + foreach (i, ref v; value.tupleof) { + { + static if (!isValueSerializable!(typeof(v)) && getUDAs!(value.tupleof[i], tomlIgnored).length == 0) { + enum prefix = fieldName!(value.tupleof[i]) ~ "]\n"; + output.put("\n"); + if (indent.length) + output.put(indent); + output.put("["); + if (group.length) + output.put(group); + output.put(prefix); + serializeTOML(v, output, indent ~ oneIndentLevel, group ~ (fieldName!(value.tupleof[i]) ~ ".")); + } + } + } +} + +void serializeTOML(T, Output)(T value, ref Output output, string indent, string group) if (hasSumType && is(T == SumType!Types, Types...)) { + if (indent.length) + output.put(indent); + output.put("kind = "); + + value.match!((part) { + serializeTOMLValue(typeof(part).stringof, output); + output.put("\n"); + if (indent.length) + output.put(indent); + + static if (isValueSerializable!(typeof(part))) { + static if (isStructArray!(typeof(part))) { + auto deeperIndent = indent ~ oneIndentLevel; + auto deepGroup = group ~ "value."; + foreach (arritem; part) { + output.put("[["); + if (group.length) + output.put(group); + output.put("value]]\n"); + serializeTOML(arritem, output, deeperIndent, deepGroup); + } + } else static if (isValueSerializable!(typeof(part))) { + output.put("value = "); + serializeTOMLValue(part, output); + output.put("\n"); + } else { + output.put("["); + if (group.length) + output.put(group); + output.put("value]\n"); + serializeTOML(part, output, indent ~ oneIndentLevel, group ~ "value."); + } + } else { + output.put("["); + if (group.length) + output.put(group); + output.put("value]\n"); + serializeTOML(part, output, indent ~ oneIndentLevel, group ~ "value."); + } + }); +} + +void serializeTOML(T, Output)(T[string] data, ref Output output, string indent, string group) { + static if (isValueSerializable!T) { + static if (isStructArray!T) { + foreach (key, value; data) { + if (indent.length) + output.put(indent); + output.put(key); + output.put(" = "); + serializeTOMLValue(value, output); + output.put("\n"); + } + } else { + auto deeperIndent = v.length ? indent ~ oneIndentLevel : null; + foreach (key, value; data) { + foreach (arritem; value) { + output.put("\n"); + if (indent.length) + output.put(indent); + output.put("[["); + if (group.length) + output.put(group); + output.put(key); + output.put("]]\n"); + serializeTOML(arritem, output, deeperIndent, group ~ key ~ "."); + } + } + } + } else { + auto deeperIndent = indent ~ oneIndentLevel; + foreach (key, value; data) { + output.put("\n"); + if (indent.length) + output.put(indent); + output.put("["); + if (group.length) + output.put(group); + output.put(key); + output.put("]\n"); + serializeTOML(value, output, deeperIndent, group ~ key ~ "."); + } + } +} + +// format struct arrays as expanded fields +enum isStructArray(T) = is(T == U[], U) && isPlainStruct!U; + +enum isPlainStruct(T) = is(T == struct) || is(T == V[string], V); + +enum isValueSerializable(T) = !is(T == struct); + +void serializeTOMLValue(T, Output)(T value, ref Output output) @safe { + static if (__traits(compiles, { auto v = TOMLValue(value); })) { + auto v = TOMLValue(value); + v.append(output); + } else + static assert(false, "TODO: serialize value type " ~ T.stringof ~ " not implemented"); +} + +@safe +unittest { + struct Database { + string host; + string database; + int port; + } + + struct User { + string name; + @tomlIgnored string password; + @tomlName("id") + int count; + } + + struct Config { + string token; + Database database; + int[] ports; + User[] users; + } + + Config config = { + token: "bot123", ports: [1337, 4242, 5555], users: [User("Alice", "123", 1), User("Bob", "456", 2),], database: Database("localhost", + "mybot", 8080)}; + + auto str = serializeTOML(config); + + assert(str == `token = "bot123" +ports = [1337, 4242, 5555] + +[[users]] + name = "Alice" + id = 1 + +[[users]] + name = "Bob" + id = 2 + +[database] + host = "localhost" + database = "mybot" + port = 8080 +`, str); +} + +@safe +static if (hasSumType) +unittest { + struct Property { + SumType!(int, string) id; + SumType!(int, string)[] attributes; + } + + Property[string] props = [ + "href": Property(SumType!(int, string)(1), [SumType!(int, string)(1), SumType!(int, string)("foo")],), + "base": Property(SumType!(int, string)("bar"), [SumType!(int, string)(44)],) + ]; + + auto str = serializeTOML(props); + + assert(str == ` +[base] + + [[base.attributes]] + kind = "int" + value = 44 + + [base.id] + kind = "string" + value = "bar" + +[href] + + [[href.attributes]] + kind = "int" + value = 1 + + [[href.attributes]] + kind = "string" + value = "foo" + + [href.id] + kind = "int" + value = 1 +`, str); +} diff --git a/source/toml/toml.d b/source/toml/toml.d new file mode 100644 index 0000000..0604dbc --- /dev/null +++ b/source/toml/toml.d @@ -0,0 +1,1143 @@ +// Written in the D programming language. + +/** + * + * Tom's Obvious, Minimal Language (v1.0.0). + * + * License: $(HTTP https://github.com/Kripth/toml/blob/master/LICENSE, MIT) + * Authors: Kripth + * References: $(LINK https://github.com/toml-lang/toml/blob/master/README.md) + * Source: $(HTTP https://github.com/Kripth/toml/blob/master/src/toml/toml.d, toml/_toml.d) + * + */ +module toml.toml; + +import std.algorithm : canFind, min, stripRight; +import std.array : Appender; +import std.ascii : newline; +import std.conv : text, to; +import std.datetime : Date, DateTimeD = DateTime, SysTime, TimeOfDayD = TimeOfDay; +import std.exception : assertThrown, enforce; +import std.string : indexOf, join, replace, strip; +import std.traits : isArray, isAssociativeArray, isFloatingPoint, isIntegral, isNumeric, KeyType; +import std.typecons : Tuple, tuple; +import std.utf : encode, UseReplacementDchar; + +import toml.datetime : DateTime, TimeOfDay; + +/** + * Flags that control how a TOML document is parsed and encoded. + */ +enum TOMLOptions { + none = 0x00, + unquotedStrings = 0x01, /// allow unquoted strings as values when parsing +} + +/** + * TOML type enumeration. + */ +enum TOML_TYPE : byte { + STRING, /// Indicates the type of a TOMLValue. + INTEGER, /// ditto + FLOAT, /// ditto + OFFSET_DATETIME, /// ditto + LOCAL_DATETIME, /// ditto + LOCAL_DATE, /// ditto + LOCAL_TIME, /// ditto + ARRAY, /// ditto + TABLE, /// ditto + TRUE, /// ditto + FALSE /// ditto +} + +alias TOMLType = TOML_TYPE; +alias TOMLfloat = TOML_TYPE.FLOAT; + +/** + * Main table of a TOML document. + * It works as a TOMLValue with the TOML_TYPE.TABLE type. + */ +struct TOMLDocument { + + public TOMLValue[string] table; + +@safe scope: + + public this(TOMLValue[string] table) pure { + this.table = table; + } + + public this(TOMLValue value) pure { + this(value.table); + } + + public string toString() const { + Appender!string appender; + foreach (key, value; this.table) { + appender.put(formatKey(key)); + appender.put(" = "); + value.append(appender); + appender.put(newline); + } + return appender.data; + } + + alias table this; + +} + +/** + * Value of a TOML value. + */ +struct TOMLValue { + + private union Store { + string str; + long integer; + double floating; + SysTime offsetDatetime; + DateTime localDatetime; + Date localDate; + TimeOfDay localTime; + TOMLValue[] array; + TOMLValue[string] table; + } + + private Store store; + private TOML_TYPE _type; + +@safe scope: + + public this(T)(T value) { + static if (is(T == TOML_TYPE)) { + this._type = value; + } else { + this.assign(value); + } + } + + public pure nothrow @property @safe @nogc TOML_TYPE type() return const { + return this._type; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.STRING + */ + public @property @trusted string str() return const pure { + enforce!TOMLException(this._type == TOML_TYPE.STRING, "TOMLValue is not a string"); + return this.store.str; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.INTEGER + */ + public @property @trusted long integer() return const pure { + enforce!TOMLException(this._type == TOML_TYPE.INTEGER, "TOMLValue is not an integer"); + return this.store.integer; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.FLOAT + */ + public @property @trusted double floating() return const pure { + enforce!TOMLException(this._type == TOML_TYPE.FLOAT, "TOMLValue is not a float"); + return this.store.floating; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.TRUE or TOML_TYPE.FALSE + */ + public @property @trusted bool boolean() return const pure { + switch (this._type) { + case TOML_TYPE.TRUE: + return true; + case TOML_TYPE.FALSE: + return false; + default: + throw new TOMLException("TOMLValue is not a boolean"); + } + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.OFFSET_DATETIME + */ + public @property @trusted ref inout(SysTime) offsetDatetime() return inout pure { + enforce!TOMLException(this.type == TOML_TYPE.OFFSET_DATETIME, "TOMLValue is not an offset datetime"); + return this.store.offsetDatetime; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.LOCAL_DATETIME + */ + public @property @trusted ref inout(DateTime) localDatetime() return inout pure { + enforce!TOMLException(this._type == TOML_TYPE.LOCAL_DATETIME, "TOMLValue is not a local datetime"); + return this.store.localDatetime; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.LOCAL_DATE + */ + public @property @trusted ref inout(Date) localDate() return inout pure { + enforce!TOMLException(this._type == TOML_TYPE.LOCAL_DATE, "TOMLValue is not a local date"); + return this.store.localDate; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.LOCAL_TIME + */ + public @property @trusted ref inout(TimeOfDay) localTime() return inout pure { + enforce!TOMLException(this._type == TOML_TYPE.LOCAL_TIME, "TOMLValue is not a local time"); + return this.store.localTime; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.ARRAY + */ + public @property @trusted ref inout(TOMLValue[]) array() return inout pure { + enforce!TOMLException(this._type == TOML_TYPE.ARRAY, "TOMLValue is not an array"); + return this.store.array; + } + + /** + * Throws: TOMLException if type is not TOML_TYPE.TABLE + */ + public @property @trusted ref inout(TOMLValue[string]) table() return inout pure { + enforce!TOMLException(this._type == TOML_TYPE.TABLE, "TOMLValue is not a table"); + return this.store.table; + } + + public inout(TOMLValue) opIndex(size_t index) return inout pure { + return this.array[index]; + } + + public inout(TOMLValue)* opBinaryRight(string op : "in")(string key) return inout pure { + return key in this.table; + } + + public inout(TOMLValue) opIndex(string key) return inout pure { + return this.table[key]; + } + + private static enum opApplyImpl = q{ + int result; + foreach (string key, ref value; this.table) { + result = dg(key, value); + if (result) { + break; + } + } + return result; + }; + + static if (__VERSION__ >= 2099) + { + public int opApply(scope int delegate(string, ref TOMLValue) @safe dg) @safe { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @safe dg) @safe { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref TOMLValue) @safe dg) @safe { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @safe dg) @safe { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @safe dg) @safe const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @safe dg) @safe const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref TOMLValue) @safe pure dg) @safe pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @safe pure dg) @safe pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref TOMLValue) @safe pure dg) @safe pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @safe pure dg) @safe pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @safe pure dg) @safe pure const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @safe pure dg) @safe pure const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref TOMLValue) @system dg) @system { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @system dg) @system { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref TOMLValue) @system dg) @system { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @system dg) @system { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @system dg) @system const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @system dg) @system const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref TOMLValue) @system pure dg) @system pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @system pure dg) @system pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref TOMLValue) @system pure dg) @system pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @system pure dg) @system pure { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @system pure dg) @system pure const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, scope ref const TOMLValue) @system pure dg) @system pure const { mixin(opApplyImpl); } + } + else + { + public int opApply(scope int delegate(string, ref TOMLValue) @system dg) @system { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref TOMLValue) @safe dg) @safe { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @system dg) @system const { mixin(opApplyImpl); } + public int opApply(scope int delegate(string, ref const TOMLValue) @safe dg) @safe const { mixin(opApplyImpl); } + } + + public void opAssign(T)(T value) pure { + this.assign(value); + } + + private void assign(T)(T value) @trusted pure { + static if (is(T == TOMLValue)) { + this.store = value.store; + this._type = value._type; + } else static if (is(T : string)) { + this.store.str = value; + this._type = TOML_TYPE.STRING; + } else static if (isIntegral!T) { + this.store.integer = value; + this._type = TOML_TYPE.INTEGER; + } else static if (isFloatingPoint!T) { + this.store.floating = value.to!double; + this._type = TOML_TYPE.FLOAT; + } else static if (is(T == SysTime)) { + this.store.offsetDatetime = value; + this._type = TOML_TYPE.OFFSET_DATETIME; + } else static if (is(T == DateTime)) { + this.store.localDatetime = value; + this._type = TOML_TYPE.LOCAL_DATETIME; + } else static if (is(T == DateTimeD)) { + this.store.localDatetime = DateTime(value.date, TimeOfDay(value.timeOfDay)); + this._type = TOML_TYPE.LOCAL_DATETIME; + } else static if (is(T == Date)) { + this.store.localDate = value; + this._type = TOML_TYPE.LOCAL_DATE; + } else static if (is(T == TimeOfDay)) { + this.store.localTime = value; + this._type = TOML_TYPE.LOCAL_TIME; + } else static if (is(T == TimeOfDayD)) { + this.store.localTime = TimeOfDay(value); + this._type = TOML_TYPE.LOCAL_TIME; + } else static if (isArray!T) { + static if (is(T == TOMLValue[])) { + if (value.length) { + // verify that every element has the same type + TOML_TYPE cmp = value[0].type; + foreach (element; value[1 .. $]) { + enforce!TOMLException(element.type == cmp, "Array's values must be of the same type"); + } + } + alias data = value; + } else { + TOMLValue[] data; + foreach (element; value) { + data ~= TOMLValue(element); + } + } + this.store.array = data; + this._type = TOML_TYPE.ARRAY; + } else static if (isAssociativeArray!T && is(KeyType!T : string)) { + static if (is(T == TOMLValue[string])) { + alias data = value; + } else { + TOMLValue[string] data; + foreach (key, v; value) { + data[key] = v; + } + } + this.store.table = data; + this._type = TOML_TYPE.TABLE; + } else static if (is(T == bool)) { + _type = value ? TOML_TYPE.TRUE : TOML_TYPE.FALSE; + } else { + static assert(0); + } + } + + public bool opEquals(T)(scope T value) const @trusted pure { + static if (is(T == TOMLValue)) { + if (this._type != value._type) { + return false; + } + final switch (this.type) with (TOML_TYPE) { + case STRING: + return this.store.str == value.store.str; + case INTEGER: + return this.store.integer == value.store.integer; + case FLOAT: + return this.store.floating == value.store.floating; + case OFFSET_DATETIME: + return this.store.offsetDatetime == value.store.offsetDatetime; + case LOCAL_DATETIME: + return this.store.localDatetime == value.store.localDatetime; + case LOCAL_DATE: + return this.store.localDate == value.store.localDate; + case LOCAL_TIME: + return this.store.localTime == value.store.localTime; + case ARRAY: + return this.store.array == value.store.array; + //case TABLE: return this.store.table == value.store.table; // causes errors + case TABLE: + return this.opEquals(value.store.table); + case TRUE: + case FALSE: + return true; + } + } else static if (is(T : string)) { + return this._type == TOML_TYPE.STRING && this.store.str == value; + } else static if (isNumeric!T) { + if (this._type == TOML_TYPE.INTEGER) { + return this.store.integer == value; + } else if (this._type == TOML_TYPE.FLOAT) { + return this.store.floating == value; + } else { + return false; + } + } else static if (is(T == SysTime)) { + return this._type == TOML_TYPE.OFFSET_DATETIME && this.store.offsetDatetime == value; + } else static if (is(T == DateTime)) { + return this._type == TOML_TYPE.LOCAL_DATETIME && this.store.localDatetime.dateTime == value.dateTime + && this.store.localDatetime.timeOfDay.fracSecs == value.timeOfDay.fracSecs; + } else static if (is(T == DateTimeD)) { + return this._type == TOML_TYPE.LOCAL_DATETIME && this.store.localDatetime.dateTime == value; + } else static if (is(T == Date)) { + return this._type == TOML_TYPE.LOCAL_DATE && this.store.localDate == value; + } else static if (is(T == TimeOfDay)) { + return this._type == TOML_TYPE.LOCAL_TIME && this.store.localTime.timeOfDay == value.timeOfDay + && this.store.localTime.fracSecs == value.fracSecs; + } else static if (is(T == TimeOfDayD)) { + return this._type == TOML_TYPE.LOCAL_TIME && this.store.localTime == value; + } else static if (isArray!T) { + if (this._type != TOML_TYPE.ARRAY || this.store.array.length != value.length) { + return false; + } + foreach (i, element; this.store.array) { + if (element != value[i]) { + return false; + } + } + return true; + } else static if (isAssociativeArray!T && is(KeyType!T : string)) { + if (this._type != TOML_TYPE.TABLE || this.store.table.length != value.length) { + return false; + } + foreach (key, v; this.store.table) { + auto cmp = key in value; + if (cmp is null || v != *cmp) { + return false; + } + } + return true; + } else static if (is(T == bool)) { + return value ? _type == TOML_TYPE.TRUE : _type == TOML_TYPE.FALSE; + } else { + return false; + } + } + + size_t toHash() const @trusted @nogc pure nothrow { + final switch (_type) with (TOML_TYPE) { + case STRING: + return hashOf(store.str); + case INTEGER: + return hashOf(store.integer); + case FLOAT: + return hashOf(store.floating); + case OFFSET_DATETIME: + return hashOf(store.offsetDatetime); + case LOCAL_DATETIME: + static if (__traits(compiles, () @nogc { hashOf(store.localDatetime); })) + return hashOf(store.localDatetime); + else + return hashOf(tuple(store.localDatetime.date, store.localDatetime.timeOfDay)); + case LOCAL_DATE: + return hashOf(store.localDate); + case LOCAL_TIME: + return hashOf(store.localTime); + case ARRAY: + return hashOf(store.array); + case TABLE: + return hashOf(store.table); + case TRUE: + return hashOf(true); + case FALSE: + return hashOf(false); + } + } + + public void append(Output)(scope ref Output appender) const @trusted { + final switch (this._type) with (TOML_TYPE) { + case STRING: + appender.put(formatString(this.store.str)); + break; + case INTEGER: + appender.put(this.store.integer.to!string); + break; + case FLOAT: + immutable str = this.store.floating.to!string; + appender.put(str); + if (!str.canFind('.') && !str.canFind('e')) { + appender.put(".0"); + } + break; + case OFFSET_DATETIME: + appender.put(this.store.offsetDatetime.toISOExtString()); + break; + case LOCAL_DATETIME: + appender.put(this.store.localDatetime.toISOExtString()); + break; + case LOCAL_DATE: + appender.put(this.store.localDate.toISOExtString()); + break; + case LOCAL_TIME: + appender.put(this.store.localTime.toISOExtString()); + break; + case ARRAY: + appender.put("["); + foreach (i, value; this.store.array) { + value.append(appender); + if (i + 1 < this.store.array.length) { + appender.put(", "); + } + } + appender.put("]"); + break; + case TABLE: + // display as an inline table + appender.put("{ "); + size_t i = 0; + foreach (key, value; this.store.table) { + appender.put(formatKey(key)); + appender.put(" = "); + value.append(appender); + if (++i != this.store.table.length) { + appender.put(", "); + } + } + appender.put(" }"); + break; + case TRUE: + appender.put("true"); + break; + case FALSE: + appender.put("false"); + break; + } + } + + public string toString() const { + Appender!string appender; + this.append(appender); + return appender.data; + } + +} + +private string formatKey(scope return string str) pure @safe { + foreach (c; str) { + if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && c != '-' && c != '_') { + return formatString(str); + } + } + return str; +} + +private string formatString(scope return inout(char)[] str) pure @safe { + Appender!string appender; + appender.put('"'); + foreach (c; str) { + switch (c) { + case '"': + appender.put("\\\""); + break; + case '\\': + appender.put("\\\\"); + break; + case '\b': + appender.put("\\b"); + break; + case '\f': + appender.put("\\f"); + break; + case '\n': + appender.put("\\n"); + break; + case '\r': + appender.put("\\r"); + break; + case '\t': + appender.put("\\t"); + break; + default: + appender.put(c); + } + } + appender.put('"'); + return appender.data; +} + +/** + * Parses a TOML document. + * Params: + * data = String in toml format to parse. Slices out of this will be returned + * _iff_ `unquotedStrings` is enabled in the options and a `string` is passed + * into this function. + * options = Parsing option + * + * Returns: a TOMLDocument with the parsed data + * Throws: + * TOMLParserException when the document's syntax is incorrect + */ +TOMLDocument parseTOML(scope const(char)[] data, TOMLOptions options = TOMLOptions.none) @safe { + return parseTOMLImpl!true(data, options); +} +/// ditto +TOMLDocument parseTOML(scope return string data, TOMLOptions options = TOMLOptions.none) @safe { + return parseTOMLImpl!false(data, options); +} + +private TOMLDocument parseTOMLImpl(bool dupData)(scope const(char)[] data, TOMLOptions options = TOMLOptions.none) @safe { + size_t index = 0; + + /** + * Throws a TOMLParserException at the current line and column. + */ + void error(string message) { + if (index >= data.length) { + index = data.length; + } + size_t i, line, column; + while (i < index) { + if (data[i++] == '\n') { + line++; + column = 0; + } else { + column++; + } + } + throw new TOMLParserException(message, line + 1, column); + } + + /** + * Throws a TOMLParserException throught the error function if + * cond is false. + */ + void enforceParser(bool cond, lazy string message) { + if (!cond) { + error(message); + } + } + + TOMLValue[string] _ret; + auto current = (() @trusted => &_ret)(); + + string[][] tableNames; + + void setImpl(scope TOMLValue[string]* table, string[] keys, string[] original, TOMLValue value) { + auto ptr = keys[0] in *table; + if (keys.length == 1) { + // should not be there + enforceParser(ptr is null, "Key is already defined"); + (*table)[keys[0]] = value; + } else { + // must be a table + if (ptr !is null) { + enforceParser((*ptr).type == TOML_TYPE.TABLE, join(original[0 .. $ - keys.length], + ".") ~ " is already defined and is not a table"); + } else { + (*table)[keys[0]] = (TOMLValue[string]).init; + } + setImpl((() @trusted => &((*table)[keys[0]].table()))(), keys[1 .. $], original, value); + } + } + + void set(string[] keys, TOMLValue value) { + setImpl(current, keys, keys, value); + } + + /** + * Removes whitespace characters and comments. + * Return: whether there's still data to read + */ + bool clear(bool clear_newline = true)() { + static if (clear_newline) { + enum chars = " \t\r\n"; + } else { + enum chars = " \t\r"; + } + if (index < data.length) { + if (chars.canFind(data[index])) { + index++; + return clear!clear_newline(); + } else if (data[index] == '#') { + // skip until end of line + while (++index < data.length && data[index] != '\n') { + } + static if (clear_newline) { + index++; // point at the next character + return clear(); + } else { + return true; + } + } else { + return true; + } + } else { + return false; + } + } + + /** + * Indicates whether the given character is valid in an unquoted key. + */ + bool isValidKeyChar(immutable char c) { + return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-' || c == '_'; + } + + string readQuotedString(bool multiline)() { + Appender!string ret; + bool backslash = false; + while (index < data.length) { + static if (!multiline) { + enforceParser(data[index] != '\n', "Unterminated quoted string"); + } + if (backslash) { + void readUnicode(size_t size)() { + enforceParser(index + size < data.length, "Invalid UTF-8 sequence"); + char[4] buffer; + immutable len = encode!(UseReplacementDchar.yes)(buffer, cast(dchar)to!ulong(data[index + 1 .. index + 1 + size], 16)); + ret.put(buffer[0 .. len].idup); + index += size; + } + + switch (data[index]) { + case '"': + ret.put('"'); + break; + case '\\': + ret.put('\\'); + break; + case 'b': + ret.put('\b'); + break; + case 't': + ret.put('\t'); + break; + case 'n': + ret.put('\n'); + break; + case 'f': + ret.put('\f'); + break; + case 'r': + ret.put('\r'); + break; + case 'u': + readUnicode!4(); + break; + case 'U': + readUnicode!8(); + break; + default: + static if (multiline) { + index++; + if (clear()) { + // remove whitespace characters until next valid character + index--; + break; + } + } + enforceParser(false, "Invalid escape sequence: '\\" ~ (index < data.length ? [cast(immutable) data[index]] : "EOF") ~ "'"); + } + backslash = false; + } else { + if (data[index] == '\\') { + backslash = true; + } else if (data[index] == '"') { + // string closed + index++; + static if (multiline) { + // control that the string is really closed + if (index + 2 <= data.length && data[index .. index + 2] == "\"\"") { + index += 2; + return ret.data.stripFirstLine; + } else { + ret.put("\""); + continue; + } + } else { + return ret.data; + } + } else { + static if (multiline) { + mixin(doLineConversion); + } + ret.put(data[index]); + } + } + index++; + } + error("Expecting \" (double quote) but found EOF"); + assert(0); + } + + string readSimpleQuotedString(bool multiline)() { + Appender!string ret; + while (index < data.length) { + static if (!multiline) { + enforceParser(data[index] != '\n', "Unterminated quoted string"); + } + if (data[index] == '\'') { + // closed + index++; + static if (multiline) { + // there must be 3 of them + if (index + 2 <= data.length && data[index .. index + 2] == "''") { + index += 2; + return ret.data.stripFirstLine; + } else { + ret.put("'"); + } + } else { + return ret.data; + } + } else { + static if (multiline) { + mixin(doLineConversion); + } + ret.put(data[index++]); + } + } + error("Expecting ' (single quote) but found EOF"); + assert(0); + } + + const(char)[] removeUnderscores(scope return const(char)[] strInput, scope const(char)[][] ranges...) @safe { + bool checkRange(char c) { + foreach (range; ranges) { + if (c >= range[0] && c <= range[1]) { + return true; + } + } + return false; + } + + auto str = strInput; + + bool underscore = false; + for (size_t i = 0; i < str.length; i++) { + if (str[i] == '_') { + if (underscore || i == 0 || i == str.length - 1 || !checkRange(str[i - 1]) || !checkRange(str[i + 1])) { + throw new Exception(""); + } + str = str[0 .. i] ~ str[i + 1 .. $]; + i--; + underscore = true; + } else { + underscore = false; + } + } + return str; + } + + TOMLValue readSpecial() { + immutable start = index; + while (index < data.length && !"\t\r\n,]}#".canFind(data[index])) { + index++; + } + const(char)[] ret = data[start .. index].stripRight(' '); + enforceParser(ret.length > 0, "Invalid empty value"); + switch (ret) { + case "true": + return TOMLValue(true); + case "false": + return TOMLValue(false); + case "inf": + case "+inf": + return TOMLValue(double.infinity); + case "-inf": + return TOMLValue(-double.infinity); + case "nan": + case "+nan": + return TOMLValue(double.nan); + case "-nan": + return TOMLValue(-double.nan); + default: + const original = ret; + try { + if (ret.length >= 10 && ret[4] == '-' && ret[7] == '-') { + // date or datetime + if (ret.length >= 19 && (ret[10] == 'T' || ret[10] == ' ') && ret[13] == ':' && ret[16] == ':') { + // datetime + if (ret[10] == ' ') { + ret = ret[0 .. 10] ~ 'T' ~ ret[11 .. $]; + } + if (ret[19 .. $].canFind("-") || ret[$ - 1] == 'Z') { + // has timezone + return TOMLValue(SysTime.fromISOExtString(ret)); + } else { + // is space allowed instead of T? + return TOMLValue(DateTime.fromISOExtString(ret)); + } + } else { + return TOMLValue(Date.fromISOExtString(ret)); + } + } else if (ret.length >= 8 && ret[2] == ':' && ret[5] == ':') { + return TOMLValue(TimeOfDay.fromISOExtString(ret)); + } + if (ret.length > 2 && ret[0] == '0') { + switch (ret[1]) { + case 'x': + return TOMLValue(to!long(removeUnderscores(ret[2 .. $], "09", "AZ", "az"), 16)); + case 'o': + return TOMLValue(to!long(removeUnderscores(ret[2 .. $], "08"), 8)); + case 'b': + return TOMLValue(to!long(removeUnderscores(ret[2 .. $], "01"), 2)); + default: + break; + } + } + if (ret.canFind('.') || ret.canFind('e') || ret.canFind('E')) { + return TOMLValue(to!double(removeUnderscores(ret, "09"))); + } else { + if (ret[0] != '0' || ret.length == 1) { + return TOMLValue(to!long(removeUnderscores(ret, "09"))); + } + } + } catch (Exception) { + } + // not a valid value at this point + if (options & TOMLOptions.unquotedStrings) { + static if (dupData) + return TOMLValue(original.idup); + else + return TOMLValue((() @trusted => cast(string) original)()); + } else { + error(text("Invalid type: '", original.idup, "'")); + } + assert(0); + } + } + + string readKey() { + enforceParser(index < data.length, "Key declaration expected but found EOF"); + string ret; + if (data[index] == '"') { + index++; + ret = readQuotedString!false(); + } else if (data[index] == '\'') { + index++; + ret = readSimpleQuotedString!false(); + } else { + Appender!string appender; + while (index < data.length && isValidKeyChar(data[index])) { + appender.put(data[index++]); + } + ret = appender.data; + enforceParser(ret.length != 0, "Key is empty or contains invalid characters"); + } + return ret; + } + + string[] readKeys() { + string[] keys; + index--; + do { + index++; + clear!false(); + keys ~= readKey(); + clear!false(); + } + while (index < data.length && data[index] == '.'); + enforceParser(keys.length != 0, "Key cannot be empty"); + return keys; + } + + TOMLValue readValue() { + if (index < data.length) { + switch (data[index++]) { + case '"': + if (index + 2 <= data.length && data[index .. index + 2] == "\"\"") { + index += 2; + return TOMLValue(readQuotedString!true()); + } else { + return TOMLValue(readQuotedString!false()); + } + case '\'': + if (index + 2 <= data.length && data[index .. index + 2] == "''") { + index += 2; + return TOMLValue(readSimpleQuotedString!true()); + } else { + return TOMLValue(readSimpleQuotedString!false()); + } + case '[': + clear(); + TOMLValue[] array; + bool comma = true; + while (data[index] != ']') { //TODO check range error + enforceParser(comma, "Elements of the array must be separated with a comma"); + array ~= readValue(); + clear!false(); // spaces allowed between elements and commas + if (data[index] == ',') { //TODO check range error + index++; + comma = true; + } else { + comma = false; + } + clear(); // spaces and newlines allowed between elements + } + index++; + return TOMLValue(array); + case '{': + clear!false(); + TOMLValue[string] table; + bool comma = true; + while (data[index] != '}') { //TODO check range error + enforceParser(comma, "Elements of the table must be separated with a comma"); + auto keys = readKeys(); + enforceParser(clear!false() && data[index++] == '=' && clear!false(), "Expected value after key declaration"); + setImpl((() @trusted => &table)(), keys, keys, readValue()); + enforceParser(clear!false(), "Expected ',' or '}' but found " ~ (index < data.length ? "EOL" : "EOF")); + if (data[index] == ',') { + index++; + comma = true; + } else { + comma = false; + } + clear!false(); + } + index++; + return TOMLValue(table); + default: + index--; + break; + } + } + return readSpecial(); + } + + void readKeyValue(string[] keys) { + if (clear()) { + enforceParser(data[index++] == '=', "Expected '=' after key declaration"); + if (clear!false()) { + set(keys, readValue()); + // there must be nothing after the key/value declaration except comments and whitespaces + if (clear!false()) + enforceParser(data[index] == '\n', "Invalid characters after value declaration: " ~ data[index]); + } else { + //TODO throw exception (missing value) + } + } else { + //TODO throw exception (missing value) + } + } + + void next() @safe { + if (data[index] == '[') { + // reset base + current = (() @trusted => &_ret)(); + index++; + bool array = false; + if (index < data.length && data[index] == '[') { + index++; + array = true; + } + string[] keys = readKeys(); + enforceParser(index < data.length && data[index++] == ']', "Invalid " ~ (array ? "array" : "table") ~ " key declaration"); + if (array) { + enforceParser(index < data.length && data[index++] == ']', "Invalid array key declaration"); + } + if (!array) { + //TODO only enforce if every key is a table + enforceParser(!tableNames.canFind(keys), "Table name has already been directly defined"); + tableNames ~= keys; + } + void update(string key, bool allowArray = true) { + if (key !in *current) { + set([key], TOMLValue(TOML_TYPE.TABLE)); + } + auto ret = (*current)[key]; + if (ret.type == TOML_TYPE.TABLE) { + current = (() @trusted => &((*current)[key].table()))(); + } else if (allowArray && ret.type == TOML_TYPE.ARRAY) { + current = (() @trusted => &((*current)[key].array[$ - 1].table()))(); + } else { + error("Invalid type"); + } + } + + foreach (immutable key; keys[0 .. $ - 1]) { + update(key); + } + if (array) { + auto exist = keys[$ - 1] in *current; + if (exist) { + //TODO must be an array + (*exist).array ~= TOMLValue(TOML_TYPE.TABLE); + } else { + set([keys[$ - 1]], TOMLValue([TOMLValue(TOML_TYPE.TABLE)])); + } + current = (() @trusted => &((*current)[keys[$ - 1]].array[$ - 1].table()))(); + } else { + update(keys[$ - 1], false); + } + } else { + readKeyValue(readKeys()); + } + + } + + while (clear()) { + next(); + } + + return TOMLDocument(_ret); + +} + +private @property string stripFirstLine(string data) pure @safe { + size_t i = 0; + while (i < data.length && data[i] != '\n') { + i++; + } + if (data[0 .. i].strip.length == 0) { + return data[i + 1 .. $]; + } else { + return data; + } +} + +version (Windows) { + // convert posix's line ending to windows' + private enum doLineConversion = q{ + if(data[index] == '\n' && index != 0 && data[index-1] != '\r') { + index++; + ret.put("\r\n"); + continue; + } + }; +} else { + // convert windows' line ending to posix's + private enum doLineConversion = q{ + if(data[index] == '\r' && index + 1 < data.length && data[index+1] == '\n') { + index += 2; + ret.put("\n"); + continue; + } + }; +} + +/** + * Exception thrown on generic TOML errors. + */ +class TOMLException : Exception { + + public this(string message, string file = __FILE__, size_t line = __LINE__) pure @safe scope { + super(message, file, line); + } + +} + +/** + * Exception thrown during the parsing of TOML document. + */ +class TOMLParserException : TOMLException { + + private Tuple!(size_t, "line", size_t, "column") _position; + + public this(string message, size_t line, size_t column, string file = __FILE__, size_t _line = __LINE__) pure @safe scope { + super(message ~ " (" ~ to!string(line) ~ ":" ~ to!string(column) ~ ")", file, _line); + this._position.line = line; + this._position.column = column; + } + + /** + * Gets the position (line and column) where the parsing expection + * has occured. + */ + public pure nothrow @property @safe @nogc auto position() scope { + return this._position; + } + +} diff --git a/template.toml b/template.toml new file mode 100644 index 0000000..86705ca --- /dev/null +++ b/template.toml @@ -0,0 +1,62 @@ +[application] +# Makes application more verbose +talkative = false + +# Error reporting +report-errors = false +report-url = "https://arch.myddns.me/bin/" + +# Allow loading external config +load-config = true +config-name = "config/$name.toml" + +# Perform certain actions automatically +auto-launch = true +auto-update = true +check-update = true + + +[interface] +# Enable user interface +enabled = false + +# Enabled options +launch = true +update = true +config-dump = false +exit = true + +# Initial message and button labels +message = "[[ $name Launcher ]]" +launch-label = "Launch" +update-label = "Update" +update-avail-label = "Update (available)" +config-dump-label = "Dump Config" +exit-label = "Exit" + + +[launcher] +# Settings to launch target application +command = ["./$exec"] +workdir = "games/$name/$workdir" + +# Uses Lua instead of shell +use-script = false +entry-file = "" +source-dir = "" + +# Windows only +hide-when-running = true + + +[updater] +# Settings to update target application +# WARNING! Updater will delete files in the workdir! +seedurl = "$seed" +workdir = "games/$name" + +parallel-downloads = 5 + +# Excludes files from updates. +# Excluded files will not be deleted. +exclude = $exclusions

))X<_5TPg{a#ji>9Q8^vNJBB*;O<(2RZCeUDjFOFX+=n$8Yp=W@L-8F zqa+3hib??ByK+Y-Kq!)%zRLzuO+wefTdhfPUGB z%wjA61vmBg?+yvr6TWMkD5rOCZ?Ad=YzVCX{rMpg|9Ko-@V*2}bC>`{ zzvLNc{gb#uwj59smt&b>O0ck2PCvtYy%HDNkPrRpTW!=G_xJDLd|BU`|9>=hc33s9 zZk84Uz<`1d8X69s{VC$y*!K?)PQ^(~t_-Ru7eCNslS7q#_3tQX0_7Y65r_V@wT{(& z^|GZCWjT}fb&yKxNIfS+^;VeyvE7mw;gP4ihjRoI@y;im_&(_^wkp@!E)*nx2f7{P zz>ToQpxn%oJ?()Mqy>#v?+){V{m|k{O9I+qx{ETsn4~~5y{DOMk+llr-VqPT$@20( zpjcyNh@0QyAGA19T-y<(79*`P1G1j0GDAjvkz!j~bj*Ehd1z%@f>$Q?S!LK3l+v0H z20EGEN<-3}*cQ`%G!K%#J&y89TlFA6M|QdbL{as4+8EHUGp0*NH_`7vN=_SCpW1l4 zEeNfDT286A9!2392H)kINFfi48KM2f4vtD*eMmG7wj8KPaAy;|ShIe6+B<0d?P zP=I?S9E?ZgBlm<_bqL~;{@KE-j@2O32o)z1R?Y`W{OV*4R=J@L~MA4ZANK{l*y#BAescGop17zUG&M}LVvX=L|7Z}m6*wMOGK_D~iyEc$Y z@&$9z9ytuqPw8G55PG`1@9zg?q^Ac^;k7Q03ga(+7d$lK5`}a@T{T=FceRFjeT`FU zd8md&D}oa9V#B?DvT>HXgu1F+8`elkt0`P!bCoa(s^XJ&iw z@(bZGCo}rdjZdY?k1G>cNqw49!Jx1}3#inexI$51?Bpl~`eav-D0)r{Wte|cCl=M8 zN+yGJa5id^ma$^CdtRw?{P!Hb#&AVA8<@E@0;=Y})Rv8cpQa}$X)$m`Tzim(qd(Dy zM3MW5ixA;GLoPnkkr(_~WVmZJRdS>*_%z{hlmNs2Q@j)r2YnIlmyvxZN3NI(Ce$K3 zVYF=_iC;XGtZnVYPEQ|k3EYO+SuKxM564-5JeywuhWMIOUz#eVK_`Uo`)&{XJEVIQ z((gabF{o(B`Xcc9zE$0=M3NVoK_Br(T@}r0pzLrrh>4X)?B#i1&o4l&y5l?S))4Gg z_GaXSP2Rzds_fPf&Q_}u)b|&NiKD&g<(4^grLY(hhTVa!=r8eZmm&c*wn8HrR|bjz zvFh=W_kCmY4Scon;Ex4#4df1kKW4~Gyxj@ulyZ9hTaVrAeFldnCO82;JEZTG{M7dI ziVe)Hcu&QT-j^eKU!kp3Lf&Z6Q$8(L`ZSnDhqazxH-~jc1J1yp0w|G>-QTz909I`= zr+6#R3E9W{BTv%7?icUlo~Uho(J`cRce*W{`byG8NZ05`2!;5Ir$$rccd2aQ$H&%yM2;o%FWZ_JN}Rf}FBK=oADWM*0@C3D9lD6&{DUS* ztbd45!5a&W#gYK$w!R#WRt{?DBtKMflCOosT20ZjTFrHOWh1znk$TrG@J2lSS61Kh z5&j?D&(sXZ17%j?KOuUk;svkIQsmQq2EwK_|NhMo6BkGIiGi0z0_V@a6`0D{Ba;hQ zWXs*72^Md>1l@E`N(`6RR(xz9@<>^hIOET5kBJ)dgS?%)Vm7$}sEfMEQUphzwznL2 zZL2f_q+z{{kfUE5HzQx*hpwE{Z1m20@IrcbY;N3N=)D7vjQ`{eAH&kb1TUft38e=s zCQJu8dUpCoCzewqeLKi{VP+NB=;=FKu8t^1u~B|Axm(f2)B3|W4@0%-E^^^P>~Bvj zG-osI!k`ZYCPVc(H8^*F%Hlwn;^6KSJjjLsUxcG!$el(61#0!{KE$@Q+ zQUGuf9a;wdhTWR+$p1>@VeZC%Ms+c1x*oD@|CtnVc*&n7(Bcens(`Ki18AcgFe_Cw zaW;keZ=3EK^z$3Jdc0fv!hLebuejzxHZ(NsXm1gw|I!GhB)N6-a={AvPUm1((TG-d z?g<8Kye6xbQA37ko%2s-w+EI2R78Rcp?|OiwA8eb8Q~q1w%*o%?M7o`ax$;Y{5)Nnrn~M_-#ZQI zAS@F3&lp2y;f#?|DiK2N;hdw~mMfWM^EqieCC7>uF}f&I;V*2%3r{mj5P4z7v|*5_ z5Bdvl7U^xGDhebwj)U34L7E|d;1KZu6a65-@nTS2w55-#SGwSHir8W>3VU>L1Ag+| zH)z?!{241sS*$$^$STfR-M^hqawmY!U`hN5`ElMxM_Cw?wtCT<5^qtPC*y<#t%JI> zly|wlsHn$V(T`N>7#RU#WE^U7hRru6$FsDtTpX5w_jOU%3bd7ZRi`rXcLGMidWNz7-Qkf z69*`;Ul$0W#M})ym_xV_NRM8GN3oCFSaGsbBZgqCY}axE z`bgg|rwW(d?$G5Q(b0{mt!~IYE##-3H0bS5X8q(R%lCt?fX&dsTbCG^MVUkqTF;%nO_5OTM~ zUxN#C*v%sme!xK^Z*OG}RdKYO3$@K^TeS$KaFhp8uy|KsC#UkVE)4WbgOS=jSsISX zCV4Rk4n4Q!@TQDTL1F?-S4{M zb_KWSh|lv>r`Vkl34<6)G|D&3YdI``oiWfQlRg*{alk6VwXrmainKp)@#Fn@_)oTm zMwt1wfJ?y9u;9CxP&furjS#xNH{#=ZEhRDc?Pa?NauMp*;k(L~Kq}!8 zq1-D{Pm9tcB_X(BJxp{g2ocWsLvZiov4$cIjpF7TttqzWS!UTX?}x?KQ~>nj>vu?N z63z&K03dn?R@aSCG zLW)$iCoPX8!bpQ#;aNIf*;mfvT)Nb!xe;HKO@oSLW~sB7AOP37-_lUUD}fo56q77w z;2e^zy*+AXW|eUi2aqi_8;;wa&ZlZ|+6|wZ0dIou_2sjzW407!q(Nr>xEopxe8HRw z@s2`=+o8BB@7>W1O)?&hP&oq#h0}nc5AUF7tA~-uOITegaO4WlyrWLSx4eCOE0SvzpD~lm9>|!XYkZj$}s4Jy(QkOUW zQS>r;TttN~BkClQvp8QPVL)jVU+(=Lejhyixc>JM*};a=L*A1fSj8AK55)fB#8NRc zt5DVJ#rt3Zd+B4of8O|FRvQHtEMmu)Tn^`Jl`_DorObypN-C(pu->Ood6HC`HV{P?@2bGm z)NHYJ#~nxBh3wh2=FpJpm~jUr57`mX5%#REMXC1L5zO#;6(47775b14pqn6wqaN>k z4ke+uA_@yZtP=ejq?wFrniCov`#yo4_VEgnHVu_@c_q(9gQyO}2qT@XN$JZJ0ennv z{y#Rsw<95doalsIvfd}uZCv^iVbs0CynrHYZ62 zUQqX(Y7^m)EB0e?0F>ZMW?-tQbz9 zgJl!i54*}RRnGcY^w&OuJd}cux7K~>Im7+>q(jgB2_5EhBk=|?rc?lrxgAND)AO&v z((&d%q141=JttRMt_;EqZtQo?y?Lll&q@J(!r^+?Xeb%Q%+j>aiK{bfs(>zc=O4|A zu-I5s$H@mlo-SN7s`saUQ!@t#wAebfwdG~WRN7iusNGsred^waeo(o;N1~eQPblJ` zL$FJtOox5bi5?ZgPx19*RvfMbO?^Xu&yU!y6+F2&*iJnvG>F~mP{_-TvA7_&L0o~OePYe`b!Qp3z zzg`?QG|NRK9lDzp_`yex8GV%KZ*JY>wDOMd!+8=WUFN5h9h|jYIz5J^ibMrcIipEc z-<$OP_VP6p931bq{|{F0{q}^q_mHUR73JYh6Et%+))+P*SSMKP9LMa^1jSvG4~Z(w z??1lWlm8O*k7ld%LqM(vZFKW%Us$UdMfH;!z2$F zu`H=*3GwRuV~Sj3&N$f)cnWE^Ko<+Kh7zA;*E^1cVELVoO`Ai1rI!L3f41vWnAsGD zs)1Z=!BN{yD_va|5S6oCs?KK~Pw4oN|AG2Zr)5V?5J}T{zhb*JN^dN?gR2AQpkXDt z?e+@hEVYuVBog@Mn(`W->Wt>{ZGQ z>xQ#6+t@f!Rq6v52xIwY-r%qrM5yokOb6gm$aVzrZW4C`;*0(Jgj zY}RpE`CLwyTf9&oi^-r3pUv`qLADjp`O!jm?UMzrzwlm82_x8n3tXj3t<)h9Aec&n zfHs`V0iVE1NPRCH8TRxi3r6GWZaBMjh_=0>Rr@&8SGo@v_TRlAN>Ir4z*VT3a)4hg zYk4`6#zvS4v6%o*ulh_O&lpm;%bpZY%Sy=RsX!~>FEubA6>8^4pnD44HVWzX@Co7v zb8_S29Pk3;hu%!@-3m&3{`fxWGx()dme7g^R)GT(I#IV@E~K8mw#y${ zU{xSJBOM`o4e$!2XJmjX77Ch5?PJy zi1?O}@$PhdQZ@vO3y_Bt+L!5($Wkng=2fU(vqnom{{T$jbvX(?V$Jd}A37<_6@g}r zO5FO!KhS>9(Yj#7A|X&3lb)3U)ku+0pcqVL0|im8n%{P}G6s~q;FFP+_Lx$CnYQ)_ zp084kveJ>epRY{B{wi?XpFAXzQt5tm1U;>&DS-n0W<}FGvP?fl8Iiccwg_j%PfX!7 zl&!B>Ax4dutoHRr?FT;9*09HlZjny#=qMs*W-JEt6*MV)W@!NG>S{@J(Y>8#ew?G660(HchBEyb>xI@g@iCu)Bod-=$ z`~0A8yYtGd=nw&;gxR}TlhA>=``dsdLx}1z#L6j-pz9XFE~Et9BJH*v{p;tR`HXh6e%-AU%OIl<*{wAfQB`=G-JU((X?sYKSF)ht4JoG3 zFshzOzO(vg_D|NtFrl``&?cMA9VW{lnvGZY7Ud;X%4MQj?;j*^O?Q@DaBkOd{ zkWtRhxmV872EEO(HXLcaHEoJwHf;AD8M?9xqXra`iDGF>Xe|?pby$-}Z@#Pu2u!cE zA%%*aA`RURxOM1aE5Y!()Q1jT$htIy2ZoUTRuaI3?&V9p|7_xKLOK=j#3!Rc@kv(O z9xk+M{}XhcmWhu1t_zLDmVS6Y#fp@*w$-%fWTulRs|?C}WV>5;|8>t#f&4gBBCq|F zzJ*vcZWmeEb!~i5AKAn#f&m8{s(9qd7PCcJrgEa|Qw1h)JjqDSDAW#g$buv z#vul&uuq+cULwUSzk`yT zqGWoKm}73es6`9i&_$1?_$z2)m?grH=yqJMFNFpDcSOl{{*gglA$VYzvDs}Bfv>?Z zf!KlmECIM>NQqq*S&3_t{Fm)yu(;?{xw>m4M7ogOkMTjVw(}`2it}B~{usP>4qMwb zbV<4KZ&X`5tvP)|td?D#Q(%_6F|Vz@XpG&49;RH_YvRWgGWf11s-B%OB*;Y)TRzCUe3=Dbj~aex0n8=1sK0hA2N=SQdNSe75-9e ziOf1_+?!vF#F+fQc3$>RH!)?SkKjUb89s51LR;*%KasMS#*gLAae{%plY+Oar? zmIuvS!)e$y3#urTx%$g)IUqqx9?VwzT;{T12A%929*SI>-0uuooo)L|(>V41gRN>* z0Cf>_Lv1H1eDMo(AolKNh0_FNm9aYPJ}XL-4U9Z>f$X)$PO3$A{sGQ^@FGH@t{y+{47x(XvMxAXR}1I5JZJ_4MT>~L;z0R zwvjx>aoyzhjDm$JGvwh;oJ*7n9LUDig2*c^3RdBO3b05Gy==S~y7C*m-Vck!-QT0d z%p}N#&4`!@ejR)g4I$Q-B}t#x&aiRihn{mOR>7swrc{=nW$mowB9h^a2#54s;rWGH z=>PL4G>#HX#$Py)G?5I}Hnj`tta^_#1f|#*jB9dW=bx_cBBm=pG&vQaJXEWY#PEB& z35-ryc_wqRGWvWr9}MmO{9zRkkkE`I#6a9ebES^M*kkK7iRq5?kJ!Punr`>-mlSBg zC#m8qj1efzMnSgPj2ze%5%ItFDZ%fwiFy05_POD0tv>C#@d5kEYurVFcL+HCN`a(mkxT+PBoxf_5y-=;5+p2N9JhF zPZ3p-C93&KsJ)I^6}>TLMvg0~H98Mwj8WBh8)augKK~37t3!^vv`VDDjYyTwIaO5; zcIVxf;vmc5U^`?pOOv+W!%B#-YBW!R(bBli=zCX*XbN<#yv`etaXQ^6Uam*zz(id^ z=#|Q>+t!>eLDG_8G_w3+3BES9_o)ogI2m<;o$QrD#w4DfUl~RgR@}ULONVjyxNzGrk$5}G*e@P5Rzdz|-t|eXm{7^zV zrV4Q#T6@cjXsYq7%${%?|)XUmB3pWSP5+zCr5SL{*iTC zo|e>guZRGaH4h$sXnSHF3|{=|zB-9zB4G5PEm&ebScrY;YiU+8XJT=vh*`xjhM5~f zo$WLX&XN$oBh=7PdM-R}A#S)^i2cop`&UfG@p|4msvhvZ0<}Ty>A6P6tn^S7xtB3A zPTVCpGKOq$+}}jYM3*aU(v28ehf`GDlAV&FhVrdhkK$j|JI>xZo3r@u1eHYIu$$MM z$HTH?@yInC9{3dfhdzWRhun?4a^`HBL(7hd(_K*%<73|O^wcuOxDfRUQ-guL@nyNz z8-%5%)>D$w2GuEajZ6|uvBJ4}CO${1oNdfr6Q@zqW(k9`+~g|ABdNS{&(izBr@j{qS?qVl)2b> zV-J&2fKhlZ@oL&1g7u`cjMvN`@UV(r~mpzkojsm z8+k)-0SLnTZV3%i+@2GbxYnaG5gS?jePT=D(Bn7yPFGUedNbhomJA3-T=iUZSk1G(~VM2=O z_WZL`go8t^y?xL)zSmf}-&DcR`6f4_pP~zs;oEzxQtttVEB%fJq?A(0P5;tY5#on; zp2vey36y+KRv0BsYZ+podQhq_oJU2OZ(sSnG4)O;7j!L|{b1Sbem~&9m&{$_3 z+F7DLj|2~h?it@5mIQCB6B33}%49QjEH#P9Cl)oabiW4tae@bp=Au~zn)>-=|NZ*~ z85zKTd%rh)BCPwy|IH4@aN><%X1@FAAFt7NZf3SbzGLxVF{$09I-=cc`VTsl8$3-l z8@TQo`YI`!jCreRhBO0rz87?oA`YJ6$$gw0&ufHVi>5K9IE!B8^`fxVVT!ucw4W3W zG!`b_54_^R3IOGv8aqS`!PJ?HL0Dex;P7BTe@ei)hE;Bk3=I^vxvQ+{KGwNGtM~+$ zFY8`YUCHbBj8b8#89%Km3|v#YeMAj6ia)l||69a)ztKj1$c{OioEHVrHS{%%-M4 z{M{FUcX!p`(r_0Pi}&GvY=;*N!^u&cDZG0X6qk^VK_|p`HnC4mL(i4*2eFsOkfCF) zkfa5wSSsY%k4Jw@zPbZ=LGJMj*jmSvg)+8BemC68wQ4H|5j$X8oB7#gqhl7!EuwFT zk*9gmn8>EgQH`io=)UN;skmVB!AxqXJ~mRQ5LmM(O6c$;PI>lt)5-d3P{ep)-*DJF zbeOWhdwdRk>*`ptU>{pN`d^DvwUX7|n2U zcJqQbDk!;`WP9J>~-%61#6Rno4xDBS5L{(3l0_8G- z7`{&B%GhFeX{zzRs0K@|e`jw0>dfj$iBr=&>Rk@mPft%VWSZ+BFMFlQ$5rbqaiR*# zLk#yO!|I6%)Pv~8uSMrmkGsn$C4?&I&aG;ylS|ewfFp*Fm}Oz4BX_h@QsaZ^=eiF{ z%UxfOn~4dONZIL)B$)c*SxPlrY!~chmwc{4YRtgGF^uPu;3iP}UoM`tp0z$fT_T6p z{cm0O3pHEVC>4p68xu7#B|`o;~b7SrcDRXAaq2}c*& z`sUvpQkz^(A0Lf~T-q&8*BvgAV>&g02jI*n>9AcRc@+;6^LurhDZ>`_vj-PBEAGjcO) zEIj`15SMm(j(mka5!eihGjNRAjFFKFCA1(6l=N|0WBT02NF&8y|8qZk2u-zw4_rV~ zgPA@;EuP+hqea^CBdpaaT||7v$vM{O)NedQ>3jW3#k8n{q^f1iFulobT8izSPla+! zXqn|FhFs}w`x*LIxczLIRPl_ISuxZ+j$~PAin;hlGDh~FF!uD&{K|uky(X++M3jZ> zXcsf~uJ`Hdzl8=lI-grirX)7>6H+ah=y+E?Nj^!1g|{?#VJuuGFi`XA2MM25W_ zxt-BLF6p9UB)rRwte3Um;u_QY60O;;+wzjfmkvuaMisZ|kj)QtajUFV25?Xn@XcXL zuXMBW-xCA;kBJDnc4}l?x*FkMu(|`=_ua6&9|>palzw&|lJy?Iy^d@qm*lk;qLk;# zfTF5>oN6)@mJyBUf8B>gO}bkG!bV(JtBzteU&!#bLX<4lEIvI}#|Bl=CN=u-i`XJ$ zTTWT#6ZK5)-ciFaz{Ewt1Fve?PNNgIgaUbF{<^<>Qa92GB)(~eHAVr3*8FAtp0o1_ zhYb|drA5rhWA$5Wd=U>Ce%Q0~F~<*7A9A)*6$`YoiJ#)XwKvQ>X6RQ)UWn@lfLx0a zS9!Ex4v}ZP*?_mgh-rM>TqpSRKr*vt8~=^tBG-XocLw zb-iZvFU1H>1y;~v0k<4piV8TfM<%Qp$19_bRRmpkj_lr|UJ=#S*4FNx+nSCqkG_hx zMuG4?<|OdQkja(-St}DqTW>-0hlb7$993|dOHQVtGuF$!kv`VS7e3b?Z$1xK*%71# z^hml@XrxM?Nb-W~f*+{#2DED{#>P&11rVQq4_JzB5eGHx5OF1*rq@-wW0pi?XwKEM z*VEI<2F!h_wCZ1;M9H2=V2rMilW{x8$1(ATFu(%C;FOI~{5euXeOWf`v4d+kw>y!* z6BtBz699W%KaomLp-Ji%VTWP)C=;nZ$}J`5%Yxc}bJZj^YG>*l6>+b8n)^Qh$a*a5||I_=eU|s74076`p{#MNL?&Avh27ot%}0*4PEO(XaT{vzzn_ z%WON@*0d#F?9JW%G=rYz4zoEeCQ7(1Jo*4^76JR-424`pED|ocwl+Jl)?#`aV$qvq zVT!M$NIEO}eKB;9reLrhV16|Y^@sbxD99D`zxOcx-})6=Kl6{d{y%<}r~l-gU;}z*1X_6T0kB}t zoWb1oMtLTjgCr%r=2ljB9K@V_h=r3~(hvP#aOJIV+ukj^;%Vfsc;QV-#3r@klTh!4 zGQ+n!8?&=>Ty)VzoOu2u-V5BHC?!THCaI_V$@p4AEP-;}ji^`Iq zaZXcN*_)w8m!wC$+oRuLlw-v=%Or{X(wefYYPTZcMFg8jKs#vyv^HFI-L;gqWNmFt zj1A^G9K8HevU@x9dVR7G<<=_;N?VQi1xnSv_Of&F_^L$N5S)O=MG2GwRe4HeN4dPb zJf^vi)BYqwe=;LEUZPD6cti-|j(s~us}L{}Qls$B3N)As6z`mfv}=E8CmK+1E2?rp z(LE;@#Jm>&BP)UcW~XI}WgAoH-LNMa6SxhCFw6Fjc14>-FmQB3`7i!5j<*_2&~GuHkSv=IcI2U`i9Q z%zx-!7=*pM0+KMTYXh?@@XVud!>dqPOU}jdBO^p$>;+a(4eL1NTCx|NMU)bqV>R9Y zWD2sCS;}wyDT9CZ1oka|pOs&J7wtcOKb!CWx0HRb3aeMMWtEY#7s_*@xpD|G+*f1&{{DwJ0tn)Ms(9k zDV(+RZC}(j#)t%1t9s2jP3q@@GQbB2*)}ABgTX+;dKg*FO6>4#?GhIqI+bd=zqtt% zK-Ju!ZnsCb+pC@WMw}x}tCf>wIaO8C?RIO^9%D4#n|kW+^)@+u`V{?szmC+Mb~b9J z{6wl=b8w0%L9L{k;Dt1YrTBgR!e=AAhRL(Bxw%P}W@4NcR?WK6Y?nnL1EC+uGsg(r z6E&r7T)f4_Ri*RH&CPPd_1Cd$@1FW+JFtI0*IaWA-}w52SZ^^#*Jy@PBGYpLMY7wN zPc<7Y?>uQLXRs;?d|B1#Z2TOp_fRXs98Qgz(xj+Ltdjkq*FpgB-eVF&r`5uivNv$n zQ57Z5kM=wUEv36@4<6s7%3@6=dvzsgILe9TtgD*?6$mmOlO!xHE%DNq-OBQ=U0~(+ z&Cbqp<4rfQ=blgU%rnoBCWa)-$kU9X8s!9}i6Jv$Tk32j32@C~>okQeM|Qnhp+iu^ z?CdO^PUpM~(P^D+Q|}*}f~MI-bI-L!7N!+hn$l{u(P`j9SlMSAE%wPY_T5!kPz}43 zgKo_pZMR$8aK%3MF3*!B+ZzVOuV>bJJa(c-X?-y5@u+|(sPI_`=~CDJ3WR-s8K+{; zSXhNs3ZujO=_M_$)C%oKP@-~HwD>*jvM>{b9v3>qGiO$80Cr(pbeE<%L4Rd7h6sz)d=qac&i!en>6_jTFIbR%CgR z_5aA1;U%}jq3fma_0GZOnn>%4{)iJ$4P+T#H1zoKc-YVhRE#_H#UJr+{VUSm8tK3J zd+@$rfnWawGk@zJGjr?heEVPiBKq_R+RMAQOkXc_HYU%yMhZCRR;B0<5WC+Bc+*eA z&98;_9Ie&oY2WyL_ybpt6^}Dox@a=S7{U+3z=U`z8_8cS$uy)hnXgeK#6KRXP z=A`JOo_-W})vXYeGEIY@$9rCB zSXo)&xnsu#p^PX?mXRhY-lqWtvULqilkIDYcOxf0rKFKala!^!9b9|uH8ojNYfXE0 zhRd%w%;Mra&z*RVJj+RpsS9yT1Z)P!P1c=S_8ctUtXbY=|n0b#$nQFIqSp>CrRsrE`}0i{b3D<1;&a+ zt3ja>jdwc4Acmc>8yQX9c*BhxzUu1w;z*Q+#Bl9(*K_%yLp*ovSkTrgoK_^r{ycVv zsR9D5fnbSj_IXk3sK6nJE z;H59Dey!qx3l7y@Q^D?fUDWaf&f&uM0qEdXqu6mq-OtD zZWJO?CW%Dv4tw<_wtwdWhY#!=mtOT94?feS!n0>SCrd8eL}|O?-;|1NY4qlHz>#l< z7mO4_9elIXT$t;pj>78maL{AY6wW>;K}sMKez7U`gt4fPB^O1=WWumVhoY~6!!Lz9 z-X?$EyZ;`{%|g3Py0C-Am;M0z>2mOuchK3rkH6?wViG8Z_+6Kv4&Mq7eN|q^kNvOk z3;#au>QG6##fdDEQ(V@fDoc{Z4#~=%>1Ie%%&n$f@H!v}##PW=gM0o9dUg&DU3Y$t z!k^=7Zf1r97hg=0Bn$>a5~U!r)f=AuZqSEdqWF6My97}PFWUgY;Vql2jwXU?wD9rWZ63NgN# zz)%N@s;DQ*+!!vs{4!RSmus0?Wi1JY{k!*Y$-zVX!QFqvMz2Sz%~-gPiZF|p4^aU# ztu~#R8QHCAMLWw#jG@#zNa;e9uvh0T{M#McSSZd%Olgu)B77B%W0X?lMqvZwYqAz5 z8My~03KAnExqe9F^9odwV4TIeihawo?AkfI1?p^SV&i+%FX8xVkD>~YS`AZ$-F`K$ z%dLZZf_@d`wZsf?t;Vl=8zO^U0~x3%d96uRHoEx2XID6ab~uCs#XY}sBx#T~RRygq zrJd`s2ftT3)&~`p^DNJ5jIXFFT}!!|@MPTOHl>#F!r6}87P%j_9{kw%U}--*`@9t4 z3Meeht%F_`GM=;W#5du@iRM{uW( zF|7;;tMs?RH^Vu;om9Yug7?Rm} z=*+@T{5@Fz-{HnL2xGsl0OG(vPr;`?K>y9Z zi0;fzojT()&_w4h~@&?Rp12ZDfdX6K8Iz= z`nmP7_hm2`u)e;IwZ*t?mP+bpCGPW^Q=qIY#5q%HgA2kDJEpFR->->?2#PTBAu&dC z;=~D#A3t78oG0P=<{C2^Crv(2|Krbwnfm`X18yRR#TZk|cWvc@1F09*{$McPBt&B; zFKV@JuPa$H4a@jE%P`>{wboI2M^TpS+_8g0mmXs0u8YP<;z}v5ID7>cAH0Nn{`8X! z%91S4!CGuJx~JP&i?p3#oue2G$@3O-v$LdGBCfi5E|&SFpxr|^q_h=PAY-GNXH8L7 zB}G{Zw@fCks3SigxhCkT#?HU_W0~M$WqsHkxdsdxrdS^uF|_b7>geTQ z3RGW4&er?=@L1NK0mHIlFs$kV28t7F!*CHoo@hL_-aR%Oo+#^z+>2NMoA#jF@i3ZE zuWIKW{LB)i4fVRo!}E3o<3IW(@D*Hi03QBwoj^&N3pL-4c8KH4yoPQ+HUlQ81tO0i zpFuzPIe7NFkhWoIAAIij;CKItg!;VUEx1?wAZb;h%OOs+>b+|7Y_vZ2yRdPFbjLo5 zD{n>TE$qTFuBuSY4D~@5zWS#UCH(3;DgUQml_Jx8ql$t2nq7QxW3_Ygeobp0dK;j? zra81{M(PibG*Yb@X|x{uGVSkugZ|Yo$4-#LnxB1K;auq1==FM>TR&IxU19@lLems2 zzD;6Ads$maN?I($NkS{nQO1a#ztNBvjX<(8OmXqGpF4MsbLY+lYhH2IGe*}iu0ZQ) z7$~A?j{^kC*E+|TlHssN?AeQAK$4_kon;$2_hCm|m4N_AW3}MNn&9~UOtZI+lC$mL z`2U_?wqZ*={%^AwD5%zUuQ6$8J~eGp~d-h0wKBM`=Yd zEWqdxyE{-lg{uGnAOJ~3K~zFwVq>+kdpEb=e*2bY&jYjb^Su5q|7Col8Fu^fdcuEo zm1I1$^EPQFh`KSFC!TzgFW-9~J_NVv1VO9)h;Z#2Gnfx3ca0!K6a;a|wPnS1S6{uF zj4>wzK~H;e4eAXBc;`{hv3YKTv+L)miXmm0W7LR+9)0u6sw7J@tgYy7ZnAUd5(!m;BxKl(rJM|zh#lxy zp@X7NTfi&u~tjn^5K^}$`S5^`O`oGBLl%6VKsYK%!q6J1}99$ynI9WwPR zzy;!^pXlhL9kD}5C@M_NzUWgHeY_RP;qD!6b}r1+&DrLl;_>HtbO&KE5g4rP+)O1` zMUC|2UJEB++h{3`aUM z2lw73%7q{L+YkzAQ)>+1%Ys2=NqXndojLKMH>un$v6-_K7KJJcTHpGdO!fz_gXR6W zRvTKg=*|o*EW@xX??p9)V~@~&>1($|+_npOIp5jn_xlu;37W?z*b&brpajN7T=|%CHC&#%R~B`quqavc%`F3s|sm+ zUXf=xyDr+rTi)_ku6fA~k`i826t*%-*}K`|Lbpu)rt%GH&uPNCPr4S8j*e$MZvHb3KuVg?Je(ImbIN8 zMgCgvcO<@9*sPcwyJ?A#hG3fO$Q#y3(otPpRftvEXMOl=5;q#xT*X!{! zKl3xZ>h{~WNH(VK)SVwoCvx6F<;b)lTRi_%;hp2-ANv@;^V`3}cfR!y)>UL#T02!K zt)(OP8JTsj(Sz@rR!WRQ{rXb0JWuv01 z3aV--5xlm<+7erei`;?TJGf|R?gjPB&N;gMBCz>w!wD=FbmTJ*W+56=%R=H|(QGk2 z#5+sreMk`W4Wgc|Z7Y3U&%$Nd=t?W!gw|AW>yswZhQvYdJbP9a_<@%kVCVd(!8x;8 z^5p40gG!pN+1%7f!gl+==4C(4Yy5mki%F8eT9@+4Z&G?VT|#c5Q$p4UvJw`~h~y6q z!)%8bF7?L0;fZf{T0KJRq!W%6N;|5Ui?h1qoguK#|x@h`#GKLg+W3LJYJjy?j9e~m23C@;GabMz5->N|o|I0r`` zhMVsY1CXj9ec&EA^)&qPZ;5HqQcWu6!9u_Z)otUV-sVA}WbXu0iWW?13-69v=S&eD1^YUKRs*@>_rI>2bTW zkt7N2yiJlAj7{o^-2{thDVhzUaHAneq6wIDI6D-F%g9_0CP0y8?VS|<{&2|b>};c$ zW+R78uj&JmrYY@qo1z#p9G11buUY(KPD-BVEG*1~$n!EV$ZZ|^BfqyCGg^zqU-(&l zPMtc%U@)j-ben3IX&x9&DQhh7limhnXM?S-hT8>dZTHX9BDS|%(Jm}3u(Y()P+RC4 z)*pL4MqyNfF_Nip|NZyV9}f5%Kl?Yi?Uk>r>p|0FU{bmr&rzLFSXm+NY0YA&W7BF% zL~H-(5C4ddeCR_w_>BjHnVXidv#{5W5^58;8C5_#^DLM3g|p;&F44+H*B4CW5htUL zN_MnZ>Fl(Uy}Wd^9-JaeQnGd`@Ij+?8l`Jv9dUaTh~(V4O+NeC&+*K$W4!s>-{B|T z_EvW9-o35SDl(f%z!S-R0_w%a4vyqO;zp{ytuX)?a^Jg*PH78dD5)MNA!_uiAF!qC-7);vjy zO)@l|w$YeGGf3u9gM?vsU0D5tE>$@o^^Tjb-p|V7Y;DF88>(skqvR(Hs&2jO{!e~VR96is0;r|6*{zI^`uQvLKXCr&~ez@=B(u92fkHN~t z@X|NH-pg^F1@w2n0$=@O_|or_o_!8?{j1Qgc{@D&IDGB{@a4N<^&}j+PQKSy{%GVn zxY~oK9-+MamiiK_y$p;IIRD}+;0qst`#uTZ`Xs#iuamT9;K(;&?F7v2f-HsBti&B> zE%`a0encjFZ>8`r?-5g>?mBFq5u)F@RhVDeV*E0xrn%6wF_Maf6u4L*LP4LryP7C~ zZ}{_%5#S=b9q_^O7bhWTuCinCybB8pBuN&g>sXA%TfYvA3B*}&W9=>Jyn>7cjDW99BREpDfQ55ywze&8Cb~Yx1l(vKK zn?uu|Cl$3O$_1W_cdlN)NK-O;C^ID~v&JM?TXAlEjnDk)r+Dhf)4cUG=53H-;)=qRqf28y$bG5DPEg;I2o2D zuCiF;YPnf$)?%x`CJh~=Hl(>Q?!Wt;hxw1so#3e_pWx1Syn`EWzIn_Zce{kN*j1_q zN>Ejm_`xTEt>`_U|Fb{iu8(|#FWq-PCr+M38C4^vwW&r_Zr0L>k+!sKI3Crzo#2Vw zgw7{5rOo);u{64gsozgwXo_2_CDnlhr^Uh0S0#NQ3GX`ul91MQra`Nfa^=M%T^&+X!K}hMTInbP zbvxbfOC;OB0KhLUx}_t`S**vWcq*RQS|XA;EtbywbPQi*IS3IllfX82vbhnjme}(_7YpH~$~7?`nAOKY@?FTOQC^;D`Q>AR?o?!U7w`Kby<$M3#P)g8?m7D5L_2h&bQqjM#Im!( znQ|^j#7FY^c#kK8K`<@}KKf2OInc%k=}&vKm8e+x@JFz&R!SVC{K()y2Uy)Y8zNIv zS$&>4&4)hxdp!2o6a2*6-pUXE$Pcr)W053H#~zkw#1OmkNk3+-wMZZooLyVvuDkBy z{qKK2k3ae-i4sSrvKYvID^k-Dx!EKMBK|6hg2AAf1)yq+$k+@_PSP>PvuP00Om}M@ z;Mnbse-FoIw@X!(wGFTE#7e4Rk3u0VfA2$JNP;#gN)@ckwb{AQdO_$CU|2eioEoq( z9Ob*l12e2_BkU*cAp5n_K$!%SwMjyFkoN*lMy;MQ30a!eVI-pTS${Q_sc`wi9}e}aLBjY_8f#S|`zg}k(2B5`p- zldrbi$K!CnW-9?uO=%wds0pY%Bn9x*d*Jo&kOFz~D17`k;Oudkig)aR6HklR{^MT} z{=m_PrNEv&C53nOxO|Xb`6EdVJpLG*_%8Ij(sYEVU>oF{A`S-nUDT8*Fithb7N_|Z3`J9<=)_kPMQw=Ic;XuvLu`J6P zosC`ylb>^}DTBdK9-S#`gI23uD+lbLz?Ky_ND?2+k6NTA;nb;9eDK2`=822=8R~thWMNwPoMzpxehiIA|&CJXQp>u7GkALj$e$=+XUT}uN4jSwrWevKvxIpUzbI6P@H%9I`!gV13> zV&o4|4t(XN${^(Lbzn^j%s$(hp{z>oyYF6}efB6vo;t#te)LToK73fDepw2N+D$D! zAkDo`b0_lnV~_LU-~BLm-E|koj~xqA5=B{*m^39%b79;z;)9bk#VKlnO8nL7bm{{e zq5SxBOoIe_y&vjT?$j5hx z6m$oUEYTE|V{tYmOVya0*fg2YNDO!EfyeKIb6sd_c=?aZI^uzk3TGfT9AEjgpcNGi zENldHW5Yt>VWtJUuD+V3y@yC|`;jfr$|Py4b|Jd)l_b}`9P`CD!J%tO+Osgfgns(r zuoeky|CooMl<*rKxSRCiYvudI&un==gut0;_eQ+GurB`5^eIlRv5+-~mxzK+CgoiS48Qekj8EwCPJ5x) z-zXuBtA*ikIF|Ak?~VBR;hdn2x+!^tL9ZvDx7H+SGP2~gRR}an$vYjgEalYMRqns{ zi<~-niX%s!;w^7~8;1@Zs_RIzfr-B|li(UCcKrIzL*M2D?|&b6ee|OoKXH<|xmgxF z9U;nA71gi^I{fkNAWESS>)^c9zl(C_`0B=z~g9va}^c#BzYOCEkhu zxkj-t*W%Wz_cK3}*4_YdPZkl2c(E8`SnE}s+9+z-oeKL#qh#-1iL62zJEbsbD)3c= z+p0qT{Gi{D33$eNiXh{Y-C}~)F`y_k1PW5Ea7IfaZ6z{Lon)w{em=>>w$h7YzyvSjJnm-5)V|2d~NirU*}#Y3k#$*ZjsI(8Z+8PS3X6kyWiC+PjpS?GDlZhASh zSKWfS<<)TcbqwcrQVa&nJ@z0x`E`NoLjgyB0e0+V#6f5@sPDY=uEm_>}e7;7eK-1&P)yU$jE6+vnbUzsTXkhk4B# zUN^Oqi^V5u(zVw3%5nd__j1oCKEYr(WXIBCeV8MhVvNB?En^-1E3C+9)N#JA2n{tS zf=H6e^PG0OJ@(&$8&e?}RicU3g_K#A@?Fh&z?@OfKS5rOR2 zufl_aa1-PKlU-I(2Cc7=_uSPCQqW2g`jogVp=;PGGzqrCRzs04YRyb%hN}+lVtJv{ zKruYet`6xJj&A7~mL81_ZjNc)_{8o%cKuB#|Ihnn+H+!{H?v6Z>}hts?#I~mV?WL6 z1D~fjSJ1bzZr`vnfnQ80{>enq_6_NtYBT`8G0D4$wLlvF-ZhYdAeG$pbN>u;`(J~F z9SmCYf@YN^IZhb&&zuG;1$?!H^#>oPTRx8ONYgib*3-HBzcKtz|A83=vqnC%zLSFA z+c8V~+S}MXbDEWFZsMYq-E@}su;Yqr*!}V!psXso$Dbzs%01-w{1;eQgtz<($t|zh zvd?Xr>5#Xjm}`SaygQO_e<9=mbfM@;!B5+wEYOLpCLa7#*s&WnpATyXCp>^8J@38o zV$Q~(7_xe1Rp8zUcef^V9Sh9}(jLL*v9YXu)0;snT8mpMLNY5GcTH?gB75I^Rcp*6 z>pt$^lLR9&QI<}OXDT}}yiia4+wq1j=2onYIMlI7MwJr)%}NgQ5)9xuM}oQ0#p@BEAnX_bU+Luxaofxu^(N1_+q=OX5*m@xYR#l1DhIT8b-GRj&3mmxQlCcliTU&QL5$1_g zZJy^OOPWIm53+OT5~of*KgOUp!2qW$OOzAof{BD3YZ(>=PBqr4TMTuWcwqe&V#*{D zF&5lOX6km+Wb?vkXNGpJNwmf(K_t9VqGeaY{EgutcG#yHc5$}DY^PN_0LII1I2_iO zT5QI;!-^-L@6jDrq();DSd?5gA%#zcNhI!pl#K17t}v!H`|;jmE7vgk5nJJ?6sfF) zgg6IYWhfJT3PTp~KwvfBtJ8 z`G0?btb%zX=($!C6Tf2IgxgP`0cwKbZ$iP3&B3tIIE3Fnqe0Iv!X;PAYYh#kF@~() zhi4w=YzZg&aH53g3s@_`&!@cNXa6Y+`w#K?U;De9ee?vGhE6E@*2#oldARzH*YS#9 z`oEdID_{s=Scl&!iG-#B~bDP9$6Uk+00i&OC$=1^K29D+AY% z!0*_x$o~EN#B^#ZDbbJB6lXnop0Q`wF6L(Euxk}rlH&1W1oIKWJ+0r1sG9T6(=SSl z785AzLL_>qwJ}3tn&Fc2kf0(Hbrcntw{qqd=4rLt_+TkG91LY&KGDn+MJahDc}~{K zsmhXGw-=JAs+vp|SDxC7o^{w8u(GtwZ7+X$ZJk(E6~q1j#gMEm`OVG!wNi?#-QuQO zZsG9ZD|z<#G1^vO=xFTY%D~k2keUPnE7AsgVZV)fpxN1OXD8V_bWN#LWWJv7@WqQ} z>}N?di=8%klF$#0x3U(eDs-BYqE?nEv{PO`$y(-lOPsV2m10G$rGp^{|ecOBlxmUcIYbfC6_Vtnm5vV^nN&T1oN%0 zFl(Ttr%3ixW1??P^`_z27n^|=kQlMpJl9weG`^QMz#seu?vA&h=9kE_Yy`>XD-_q? z&e8k6!SSIKeskbrUh<}QaQH{>WXGk4an^G9YhUEc@A`KX4)ly>urV>=Im^s}%cRK6 z%x-CJv-Sv)@xSyR;NI86yZ#n@;2*=IUxv5-GQ*VvBR2cA=fpes@c#qP9ub5jQ!?!X zm`tX5oq+9%o8X2Z9~%{9CI@9G`u)0)$HsS>iOhwZjVAvq7M?84WcM4K`XXaapJ!+& z%cA~gqs7E0>iK;rE_t3Y8~3vHSu8`LRKdi@)dwVo^TaR zc222PRn^GDFd`6f&8wxkX?J9`R16C-xC-QF9W9T`5t@^vsTk>4OHr11;EKyG?>iI{vj=a@BfeE;`-AD{iqXZY&ZzecyaDFJyZu9|ePp%-#= zl4az1r?xGwT}r*jl~(dlDnXVKZREUp&#)9zpDfGjWL@taNtWig($%o5A%;FkYvAk4 z+18Mk(V8^N&|V;n-auYVl1kU&oUL8o;%!!W2VS9lMXx&~&vLH2;d=J$*+Wqj@?wz( zOs8Sr9?q?bF{Rn^#Hr2f1+5^nCrhBBv zh9#ze9Xr$Ix%DANNBDj#nyj@EWFdI#j~YN~{jsXyNnJxls)0=FpifpN4U>Z({-po_ zAOJ~3K~&IC$Rx^Pom4v)&Q7Hb#%u9E51}GPYe5ErdI7DmD2lSI*C;4Ww^DQmo_4CS z)-$w@qN=vUXEyhKP1$HO+d95i@#2b;$YkJ1ZR(V@QTz5XeCjxE?KIgHH=sIF2$NQa zU2p%p_+wA9`tY5U4iXQkZxrjMJ706~(i25LqP_*=L;y4K|3>G)XTFPm{OkBzCfw`F zg5KHFtX5F$oa5$q{xVm;^=C=u7wbzGAm4crSN)YY(pg%ewPTt2OD^ME@BR18tn3yi zMkTonrUCuN%Xf?3dT|+E_jc&a!*BmQeCEC2Jo@eb2)(=;)0u^hRmhg`!vRhkLHC|~ z2tNL=M)?FL8SV9l=OpFOjuZt1TXGMmm5b3qsyEG4=6pNh?aoG36jW6x>{^p&Ijwe! zEJ-M;3I>G4y+o8v4RT++XKV=O(X|nn{N5tCyH|dG|iZwU!>j612WJJg|rMvmmNFvu`!4Zar~?&)A}aw#qG|< zcE7jD#@}vApSJsN#{CvWQKJ)+`3%hlFr9KXWZ3KlcRhtlQW@xcvw^T z&T#Fu*Kx_gLqZ4+(mtaNWmvByq2Na*VSMeETy`1PUUxm;e)wUAy*^1R!z1?hnMqL^ zY*{iK48#+m5!O?$MZCx3g48=G1_Ht)NO9SC4@Z+olB6lUqKoyZ{IF4e5Pksd;~Qw| zX+O_%@>UBwEGUbjPQk03m7RLbxvsN-y|~VKN98@6-AyjrvzwQ_^j0b)IKU`PlBFbh zO7GkT4?p%0rL|mf<>A@{!IlJ{KQ)r?msnMiKi^}E=+tCp;TB`(HDP3pUB1;XWN@ePgMc2c^ zOq+z8!`J15g3bL4F1}eqo4UMX$RO8a$Gu1s%IMede>n8H|2e{?t*^4HQ{OTS_7RnbV;;(kPWo=t&v-vm$>e zzAqQz!T*A1W713~N$SsL@~-W6yY-)&Wm(M&m~8Bt>(=Jy*&MjWjJO(-ID!ng2>bWM z7@6pU{@w;B#3;qAiJm^XnJO;cw~y;?ype^)g;8bI!nR*KyTgBC$a1msx?iD76hu5ws{!mCk(TCJ8`1!+o}XXJT`M$sP( zz!(O-0hO~@FL$}uy7&U*Ik*~=|A-y$B>bpVj()XC@h6c7;2RVr#wj`fiFHs zMk^8nN~NQnRz#8lga(z!psFDQXN1654so^=M=d<_?Hw%dn4{B?&t$z7g&Mu(BKaC$<@L;w0ZF_)I|n)Rg~T7kni_HAyao-{kPIe+@hLqKhH<%0BqLe*t%Y zkhy(3+4;_Y%JQ4uF{WLP=QK@I(#1u&)PphxptHOSU`x?&J}Z-^DD`I@_#*0MuSd@< z!MDBuU;8qA`)%-3{}5jN7VN?6AZybxDcK+X20ZvjQru&_;{Y)wNG3QEp+Rz9&Z}2o z4qm-&afz;slRMKFIvZzJSB2pnCv4{^tVNflcoj@Q_R-GQHMIOmlA?{qR#ub%)&|R7 zi?`#plolzlt!cm0-n~1dr$DOkKM)l-t#_= z9zBXSn&U^G;pmYkdFz|s%q3S}RUd*&FTIp&uDpt`-2WwPRWQ?<7Z^r~&Ngr5l15Zn zdcAIlm$kL`zz7+bej&urp13!hgqWIN-ELQiI-xVY(1#>R5_a#LWo0hmJI6|N-ocm* zor-aft%i78QS`gCRmJ|58Rpyhwo;miT6pj24NCf@Tn>c|Dgkd%%8;d|Hq)tGnBs$E zPy%&EJAP|R$x9$O^)0~?4S(?O;PZEHE$Yo3zMmr5 zn}q+H7QS%^&cz!;c3Fk6-_Jb+tj=41fMV(^_02x%a=p zhks3)p)3#>o5n@ubYf)BiRxgeVSb|U$IpF|X!c^x#&B40=1j<#`mGmbG<7rwBo7(1ADH9-VF=dMuz0J&#|E_0a0;L%ahxGe>j4^e{%?qgp z;tJwI);j=eYipcYT@^NeKo62evn4ROt6~1y1+r07j5fIcpSL#;vMf96#C~VF%Ug2K zs_Lq)>U~qUmR6&Y07<~iSjHpl8Dz|uU@-`WAn-;E9>U>KIE*J89*+Yv9y3NG1|zU6 z83;4LFp>}gAtXRTQcJB~)ZG%jRd;P!nU&jH?!9O8AKy9Wo_q6Ub#)_@5f$B4mGxe} zd%t_W?YC%){n;Fu%y92L_u{r&Z;dO5$-yCBeBlNB)^Gh5e)qS32U|Pa0381JfBy5h zaN$L~;~nq7&1cVIJQ{;@hTHGB6ZhTs8ocn#^Zv7B&`nJU+XRa+EDE~kjKNuh+8QY3 zCt6B@ahi-s!O0oY16q|<;Lag)L=Ti+!$DFNfL0{HSJg7hkmWgaO*_`%XasE?s=CH- zJRs2>PDx%hH1bakAC8Q6{Kab~4Nl*56JGne*JHH0L^7<0hxqKD{yF~7fAx#_i@*3B zU>!zFV@N4*`SNAF@4fHCSD$(c|KP`e9B=;CZ$UX6;l#-kc*8>v;_M&ag57Jo$wO$N zRadwtXk^>oo-gda!-y~a3aU$eLx~X3>6m?adHK4umsGR64`LY?IhKbKR##|dG;xu| zzyswP&-s;DT^ZuuTW-Rj%&zNM9SW4ad5vpRjWXlV)@NQMhnu$0)kV+* z7qG$sv$6{O@-G7){s4{PfAD8XG0$0GwdLDK#Xa<>d?B%$-c%sa0KMlA>Gk_xHGr}K z@}^x6gyLZPFNu%$Q||?q){w7mUiW(RnJslk@( zUjS}J@hl*M__8dI4svN{TUB-3@rNluT46Fqc$l&j5Tf+J!BF^^jtXH)HEx;)`}_NG zXa04Ijl@|myw)NY#r_$W8fb-IH;Ts!_vGN<06V+8@exy6LmLArNCKYw?l|Ka(Vcx# zO>;_^kThE3ButW-cO;zEupZzR8@TG$C+Z~az`$^v)Zbr&9Z;C_7U_kSNd+dCKxOXOMBkw@lSKq>7hnx5go z5Z8O!7@|QlipOBG)>IYt_Ya`vHENN8GlY@fkJ7)(6{XcfFc(d6d9Ompp^zZcb_o^7XUso$Hww9?mo8( z2G>beseNUfR%nZ7x8}GuQz%4m-D41fs5*0HNFA)H04|UhLrCc@K(&Q4w0pGv{jD`* zo?|qakl=#sk0YQ-=A_jxJeSx4#-oyz;0rr@&Pk|9fq^><2L%IQWtd}an8!?5 zRSK$ZyoDx-2uaRRH5S~pcA?ihi~@Zs-9v`!xJU}LkNl^la1Q=W-%j$%<7J3y23&p~ zI57ftr@%*l4*1lEfa#V8M~Xf+7vnXRe{lgSiyUB|Ba>k=CYs4no@kHb`j zd-7_Me(1nM&XH2Kc!eH=L;KZlz!QXmB{US>oYMNc+int+Bvu;bt0e=mh>?aq^kaR8Jym`;i9!5NF|ZO+)6BtkNRMaCGk zvzU9Z1WENX2q_>%hO!(W%W|l?foT*36H!+^?CASJ!6L}G#$+-tBnrH{Xn} zJo*^k|F8cwKJt-|;NqprSX*EB!ZW0#g=l0jf;I{-yl@`>+t2+x9{%FP_{sm`zr^i# z+=+YdyAPlF>}S9{MJ#|LxCi2}XmCJ#IOR-|d_@H0rM~PTK_7Q$F7o&eL7Y~^oiSiC zDon>;QZOtH3JeBAOg%Nu8AU)pU$|JKk#UFhmEjQ`fe?f##bx`T#!K5XOdE?*Fc?3| z5hi^gb8s%bxQN2EA`f@TeIhJI1UzagXf=bWro?51gA^IK%)qk(T;{zDMzWX=7S?MK zq$AKk>x=yTw5#@XzSYqPgF)sGRidUqG#C~Fhc(F$Pa0a`Xg!XHXOQd^QX=y^RwR4F z6cv2jC^6id@V!S2LpDy+12@?xTi73X5Ad<~1AqJ*!0rT?eAV0O_PTkuV5~0|6a^{J zFP#zu$zRbc2Ez9#;IIIe{^2izt!$7Q*@D>UPoDY!$3-#Sx0SBzy2HsnE}?b~=Tqn4 zPM(Fh_l@8$eJ^$o{sGEw`wwBi|EFQJLU#4Vw!=rlTJYCUd(}YWNS=5gfaTloMX|JU z#2{wTS1RWk)*SAb*r24OI^29Jk{VbmBXunx?*p3uNHX-hW6nrB!zM0$&RXyuz>Oyb zQ%Jxxf=6ex-j4Cn!2*ziY8n{9sD~zZVF*efxqvclj)?eB55%ytvW)R~e1wYkb&ri6 zRw~?!jz&vjd!7oarIWkpr{LeWD2mSg4N09b7Oj>;u@@#Ax@jPph^A$+;0WtJ5M!z+ z3ViD~e+%xr_g*~l=wtZh_x%z+^3ji=swylmjj21&2>I{4P|(t735{y-$Rm&7=l<7! zhUfnBYxt2L{ZZU|-+g$)8z01Dk3C9738?UjsE%H-WjhB3!LhY9sGAzfXsCwrx2lP? zA&U$`a+rqXf4}s^aa1BW%d)t? z4SdxL+cP|Obp~fF8gOt%U6M)!9LOqHz*-Ki8)(&#K!hyXB;lNA7t~O?0TeMfv@no< zECwD7gd|w-fwv?m!I=ezjJBrEV?afe4~AC_On9lg4ttb7YJGMnlU2(i-5+-$^I&`6qy9A3q|p zgGE@Qeqy)1f}k(#lT!Y4PYb|z`jrLj>ANCo{DzGgFMO2lLzaOb>;TVxxl2>*T^Gq(Q6%jEZGquizw3smV`*%dBsTg5 z9wiWiYrDHXfn?F|yr~;Bs)03i*q$-&r+e0~G2y3k7Fv7!fdh)7gbw)C(v?*(${$`$-y zzw#@1?)-WD;P-t$&Yr#*tE=m%RfCLmfuh`zm2)^FIau&XgEi!ZQ|5$eW8QUEHM9Z> zG<@gT1mQ|b0)DWFyeExja(q%s!5V|ve2)2ij(J@}+oZ~60$h?jkF&`Ln*%mA@Nx7Y zj8~Syxxk-(`qQ|!vx6tT@)ZciQIsXDGH47rA~mWZyTUvp$?mFxF&ctPoY>q%U03+T zC;kX8zHlB(<0aC0&%C6kuc`sSX%$%pG=|g33WCH$qSBuaxDZg`Kn!buG%17xAAWxv z&7>dTeLzw8zNJx)VJ>l~NXMQ#3#%23Y2b8&K_PL^Et|+QaRg(K{ygCU*`3d@S2<*o z$D|1B616`6uz6X^EGr=MA}Ud-rh=|#(Df9isr+7u0a=EOb4Z!PW&PWe0U6QWOilP8JxCX3jBqOvEm~FR7KfO*#5fugiwFT^$!QFi4 zkzMX0I%as518XP5K$=uSZ0zptVtZ#NCTnYDOyZm|4-$5rv2$my@5OqAkp90M#@J2> zIL5#PLtd1~d!{ajhliL>r*SP8?893DurPse36fnBTgRvfQVqHtoU;giO-K4P1*v+r zzTsJ57>!5`u&Sz9IDJE6W5H`K+S#Yy7h*hg?crLbuBl;tQP(w`2b=4rffFJEvgh-8 z>pz2*u|&?U#CBp{HBSnTPk!Q$arw#>JpSd!zyshF z;u@i)65iC~!i5Xi+uOr!x81hTDJo6yY0&k@`q$kL_x>*3l`Rbm3^J01WI_^pUN|sA zlajUN68GJD0-482ghC};v+z23o?}*NT-s|eGY(lI+#@6ZnYTe4no>Xc&<0R8cmq^0 zO$AlYY1eNJ?mM@EH{X92+xrbZ{k0t!Rl_k3BNUo20Z1N1Vi5|L==Fw`+~BbBJYnZ2-i!dKg%r@LK~=eyst0%=R7=?j_b(OrNblwK?qmO2 z#|O}8@GBP}9{xD+!lRU!MIyKpI`k$v^~C~|e;@IWB=M!|fZo5ej$HC83(PdoeECZ_ zbLmB7x84WzEUk~DWTm^*{(+m0xl=TE3Xto2wD$p#{ZTq&49N0$z@nK0fA(*IdDHFq zdzuClLumfm&>s!o`0v4;IOEapi$}^Sej%0SU9{#2v2i$=;M%oaIIrK3P9C|Z>_v%M zuWw?EjvRfTZ7Jzzv@3RLEOG8}PYkOo%h9AOT&oKgF5t?Q%P~oJL5tL}lLRd7f@x&$ zV6E~%Km%hKjA78)B!WLUf&*v)f$m5$9*ss=UtjCU9e+b&;|ADJi>SC^?;oaHVHJ_a z#&|r&-rinhEQKOwHk(0sJ7x|t@S({70|O(qMytFhhyWK7J3Bkr-`m4tBFq^KiW1AK z%g8cX-GULaUwHLPqYa61aUM;gq;?t{H1^K8M57KdJv@N54rN}#8seCqI&~5oo14D7 z&ZrVq-D-|=L3X^hD>gyC)RIQ9M!`DcZ6k??XtV*B90DYN3+^?w>zYnGuSiAjPV@hB7{R%6;=z5?|J*Z_*-wf8()0-68`+j zmr(1Pgm|=qtuvYcwXYV5(=CLcQAAl#72Rl(H(YS>!^l5^T{!(27ZPQb(V1op>0Q&R8BTaDf7d26 zV}cYbLw6SC$COHAY9?Szc)LZ1##MmVf|pt5O=Sq!0?WY#gDgu(BT>(0a9Trhj)Q}P zV*yS#(!nosV>(KaIX+mIh6Pra24I{K=T|FOD42%2?X_`?$&$iHC~_eUbRa2MJtljCb1f zDHQ&k^2WwSXTtdnkBwu%nlD#O^f5XiHjFWN`st@JnNI0*EdZe# zr7$@>L?*KKGkKLg&NyTyVYKl@R#>HQZ-Gmzo}l(;w11v>i%AH|kIbLrN%@^fPymO3eB{wbe`#%X^?m6< z*3@+VfF=Z1R#z|{455vN1icvZEMON$6uZSlvMB2FzKEhb7*4-z`{M8lX`I7p@+{G6|8Fkb^PG z!3c%))vR_={#OX15OVn4s6VKzQ7}fqX;K$+&PJ=!)lmV#yT01<%HZn$1d|#lGuh%6 zeDY&lVlXH>LL*JnL^Za6HqNqap;^eH2~9XGg6K^+=wobz@4xhncaB5rq{q6`UuvU$y-CgWVuLY;D_6Hs z%_|5gkU0k~B?eML<{5NDvb%xes#Jrfafx1l@IpH>F}Cu~e#St-z%m3>(Sa)EIlr7WA0Qr^#;ieo}MzY}4!8Xad zt7ZHwEiGX@9(Ts--_Y226<;ZXB{WB=CqP}-FiJrrMManpXltRHhA4a{5ghWxo|LT{ zYRDHEIx>(~<^{MS_Xb#576~`i6?au#(VP!}JW4!fxIf(^*RjkpWg? zP!t%I!}ysQVzZ89fLxPXbn5CAmeM4?sSX66JAJ9=kk17Ylub@{yu0B zFhpsLI&h3B>#T->Y4vX&*;k#jJX z`|+iNV;rJy$YTwRRiq{0h-YlL!0Pe`iHMH84OXl0+ZQ=hQ}9CP}^X zX1#2#ufy^8(22^@OAREj@z8gGc|`xB*yy9IUk-qJJ?2BuK}a1ZQ-`$c;U%P$T)*5Sm)`Vo)ze(@Y) z!#RiT?Hyd(*`e3A4u(4#LApp7hp*f+kP{g_n9gT7kB&x3aQ~wY9Zl zyXn8y*tkw?riDX)A`p=L{n!t&(Fd~jW!GIo4~#=N)*99uqfsjy$thZ?j`e$ZU%FJb zyTY&<%#!48;m;$@6u9e7r_$@yFKXiof^n$2#{T|3@+^&F{|r% zorBJF#);NvEba9<12Qj!!x)3M4vnH~Vm*rAZ~-nH&Tg*Y+=(%iQaG$EE*&z+VjNun zSv^A|1Y}l1O0s{{*1%~6?WYXZSuoC{Byr9-w2$TA-9K}xgitM{cMPFbRumENP!k@aJv&^64%e}u+U z6X6o(ok$XVAGyzayX-|>eyZ!AP6zz=a1NCI{jwpD-}}an9)CYJ`j*70etJ3z@5gPw zfbILqrwVyDs_71A0VaWue*l>K&n!WLM+&V{q2KGzEGhNPEKuHZGgiOzdyf=o&N=Mv z?qTcd7M^|X1#GOZVP$#gi2p{4XGmj1YmL8r_8DB-+KOFSEDZhFHq~6>Tp;HQcG{e1 zbg?J521aZ82%VoJXx0@mo*hoe%z+D3O$}p> z*Q}SAPv_*q2Ntak!)_zJ07436K?O-^AE1)PBgu}{I!B1egsu=rC%TDae#r$O1(;zS znM@=PSwQYvIO6g%fh?D>&XNn0(Ve|jpkK^p(^v_XWf^z8seX3KQ4JO2aYaFzXhI^n z-Uw@bWr(Fw3E+U}Vp&1b#p5wftd5R64E+a$lCnZ$8HC?arF1?U0DX)c7oBxz92EkL zQ6WHkSK8HEF2LZhIvU{3ue}v#POQSg;j0(+ap6$Ii42SxNMCRXkwvPJF*X)?;DT%_ znIv^TKVBv+1=?j9MJj?;E37R^ER}hJVRLA-1>-<288X4+sIxX1W=#ta=U`Bll(^u! z8sX_d(5J8k7qZD@61)F?R~QbiPHd;X9BH6uUoMD_JTeGPE&?S1@K$%y>4vuMSS}B6rLd0l~Sb0=@Vn>w6=)48m?zh zPfQEnw0L5Sk#2*`f&FdZBmc53Zn(c*ihe0C*b_v1<`y{6z?r}O_mOR!>U2Pdhf`eL z-ojVE_6#m>ZINh+lt-kTqr|B`8XH<`Ja_&@T)ld=~GSy6yn{!=B)z}ex&U}9r zXyW%XSO+XGFJoksOU%u=|{S4MBFjgjoTDX>Bm0&&B-@=&1`**F$oJ?zyn$G)#_@3z`B7EjaWiVG3 znMc%Rf;xKV0Of%yE~3FLn00jj5Zv_trP zTITPIO7t9n&+)+oO(3uYAUbsS^@1L=rXDnaU!tet@G%^HvO z0P>7uXe|Lo7bqrPuRF-Htiw6J-dBtbAzki;nWM~vAVo`WQ4pZHma(^*47q{%4Mt0$Nad|1#q5a5e=`ssY{^mb=GD{hezCh zLVkxcZPTwILR`*fGwkp0`{zV>Y)KVW^$1qtASL(fCgtCnbwGRVsF}K05+|!WxT%2j zPbaf3F>2Y|+`#(!`azpmKm8~yYP(?w_Kad?46VAZOsu)Dhp7#qj+O1YR^Uu{k? zO4Gb#0c|lo|7nuYN=bL7aemz$r;3R%9&_wiADG}6$QeV%1%yZZbIxIuiq_jg3YbQr zHX3VwT12D%Jcp`lFfPH10@HboiC6CvoWNN{mZK~RKM^p%ptUhPij3xQ|Dly?1z=*8 zuHkHI(;Cbx{H{c`cbN@~F}m=YH=Ws>UWB?!vkF`VIhhgaj)W$M>{%Q(cO_52CGb<-ytwB{)@gWK0 zrBp*(2!ZXxDX#3ds$`9}F#cz+z4;DvK|zl=s?P7-wQgV)feM|`(VS-}fk7c+_a3?% z;Vq6s!qf0M>) zD0%&H|igV2n_XN*S-#7m{^Gx&{!slo{%##^i89_yN`yO{v6tKOZq?F{>)dW8PJ?_SbSco#EhM z0;P?&Y^+pMK(cl}XdQKM)@W#> zz%`E}Q^_Tk2OMQt#QPv$B_g;FmI|o;knH<3p%@!Y1y>AV95B_??T;NWw8<{NZ?MBt z4iRY2-SmPy?efKf*GYBzIe_2zpD_NOe+2uww;x-uzDkbO5rw*bH*+K7*3Me2sep2f z$^pz0PrtUnt_SedUX*BV+Z{g&;Nlq$@;z@k+)1Qi31%^oSdPH)H;G6P;(IST+m3r)zOJ#cpi}NQU16n=dY|+iQ~T43 z*<=ExYI>xcZ(K-%E-8#&MNaW9jfJF~V!XDEg^7(VcO+fLz=32X-Y5m*Y3 z&wD;0i>TuUfUyR{;Rvg1tB`q)xgYJPYtRi@L-P9jmu`xb3E8+`K-seVGe*f0hv*YX{`ab24F;;J9lygCss;W zYjHTQusf|fbUNp`^pXL{L@d;db5Oc#VJanMFQqM1Gl$a+U;~<#rVHyM5myz?5r2Ps zs=-ADAv0u>(0bFM&HECyhv-V1%&PfBlF^gZF=NI^IK*RJatx~WlvqXvzm zRRhd8uq=TkNuz)CLDY5uFVEnpRy}&jpZ7X_!2prbuV)?xKJh{D`@b2;idRIHN|_3s z&w0$+qu(*7E`MQ+nOYtXhr{++agKhz*S{V16CZ-Pyc<8ZUMn#8_V2^9ANsYJ_-oGs zec*e47|RcQ6P)iXukG*Q#S0fP9F(Z48r5)!p_fb*j8r45rorbv|1hT08ScI3Zmg}X zVKf}ZqAuL`>2!)`UU&hM$u#csTM!)`ZZZ4Y6zh!GZZ;hUrH|;D^b@OMq}Mrg^nDI^iWW|b zzvB+O7#n$x=EP}Cl*i<8KjBCxRB89$0T%ct&?HFyMYq``cz_Z>5fXk56k}3o1b|C_ z3G7`3PMkdwXW?^%>(Q4w?F+HcLF%G8*CNVQfAy96ulFgD@htEzYT^xV!|*%bjmfY5 zJR}1g2X1-y&qA%9!18bY8jJ#_AXmQ8sWI;TiGNJWWgvIV@o$z~KlV>Y%HX86lsNW9e!I246ZGahgA$t?oAG{3CKJ5y!g*9xg`z0ooI%ql zC{>|pDgXrHD$5eX;n0h4wKlr6FX!H0rGZjFo|itkQ^75S^nUKmalJd88B*Y;n@;1z zi4!qy7RN?c2jc4*8@)60dffhgL7NIVb-s0bY*bZ)oO7af>yU^Im=&)$r-X^m zSoFn-^ov_jR83ZBgA;VJSQYip|*mLFI96;kbZV7R|b9H-RhjTqY^T6wN&b_SiUq4t=bBgfrtd2{ZSX~0L9L&&2sPNZ+ zHk(De%RJ9JR4m3A4rUsMwTm5rVn8OS!{?4c8H+}1IB)*L!2p>IA0G>5L_^GIEdjA@bU1v>=Nze=hG=(x^xMfn`=08`ZR98 zKSRTb9O*5R~AR9CG_5+Im}Jb&jLnnrcj2z66KfgM5cvtG4keDM;@Ir^ic>ji75aD!k) z;DV=>?;@j$;~xTtLGGZd3Am*|*<2lUC^PA(I*zG1$ECdnR}U2_;3XA$?Zs~5=kbnu zA*3Au#sx%9peCmrtWf|QPOpt{?!?HCIyIi(nqg9@2oU55g$rQe^{vD5kaH>uLie9= zT7@jy%2{OKSpjDq24#Ufmq)-uC8J#!%LH=4AUG91${J`#lEf*^vQNcZT3YJ3EQZb^ zMfB%+jiJo3-qgINvCy{3G4o|cc(;}6L`1q7xj_ptCY z$>gB+|1LAYXrKPPT&D5)?q%S~&%wR+t>A;PKeW5D*P;6g#ZFMI6G8ybd>Prpe*jb! z#%J%L!s7fBq_Folz6zCYEa7p#g*qafsOSwjD`bjZC!yi7D_7**dlONR%DpXW;mQoaq{FQ)>c-b zj6tmw4iERSy}gUAD_1cbl(@XL1qUD#0!j!7E})t2t_l5~o_R=oAJE*P{wAGq%2)z` zvM6!-)G3U{V@N46o6T_k{CT|e(u>&N-$$0w85ufd=PZ<}qAag5M-yOB<0Hc$1*J^X z>Tgl|))xs9Qf7YlpH64V4RCF312^A%Ge)CPH#U+EKY-3cVr{(6eg0RBjqrKG`}PZ} z{;vBtbEY&-ilTtE7SBKX9A;I8tSI0(arHZ|{VH=xC<@Y_O(T=uAidM7 z(mEPJ8EYY!fOcIvXjN5Y-osgE=WqNuHXe_Vtqr|UPjGmXGzs6 z1ZCjv2Y{CJR;V>&P)!5NTxUhVdlZ^H&tR+t$=A{V03ZNKL_t)5^Ew1@u2Uogx!!N7pQVe85jJof0Lc-yzVy(4mR97QD6Ob!AOp&|}+s{YO|<-{IW#jcNXKvgI+ ziNA60859c)R{GY#^Tyz%ojDFGk{}k`?@TQv+(2_;LV_pMJ7Yc7C=_YFGl9|ATpHl* zuRDu#n`0Pbus>_?)r-5B&gXDkf^iB&;hn~eb8w0K6VWnhiD;~Wu_Ud`ge1F31{f=# zIR_URtkL97)x!@ktH4bKqZN2YRKJ3AFjm58g~oEy>wg&`>KU+e z5!yZo-lI>2B54r-HkCUL2=2hz%OC#?@bO;-4iD%Qy8U&q4}TIWW0+fq$^zN4#GBsp zFCd2FBlmN4bp=bK5e^Ry;`_vrv&fL?jGl9?(9{(b0GpdwU0%juPG{cyKE~#3eE(Wpz~mDa|5^Eeh1+Z zguwRpHlBU`LcgwS)O8)Lv&p-~bo>C) zasHy!XDTYBwZ`G$A(YZsTU!TrfU28zWdB#pDcq0fwFgCq1~n7_{U$g}g966DIZI?7 zKmF#3BV+4KtJ|}}-;2gt42m4%(TG6l&Vg|T)hO)m?Gu$R06G~%mK-h;03Lq$^MAOy zycPiloN*lN?cvJS7VfAjSjM0m8eyC{a~i|(7#75-4i&BqXBXpGWCNKA311_h&nTp?40Vq>N7b_Bf_#^q^E5#MZ7AD7GjftO?H$g^D;Ll6IK z7OSRklhPnfgD<7442MH#t)tUl=Ba6Yboin@Sc>{TwXuxVLVz)gJI}61o^JR)qVu%- zYilj$mBHRz5p~BHRJN7lwIBt*uur$zp!S`h^sa{ro=@+Ab}Y-WzB0xwC&pmRkzfck zu1z#q9y1H>9ArWjbcQAraIN<^xbRM99Gtb|Mr$3Ev#_dx)j>(oVKx)dVXAYGbC7GG zs!>UaT#zajxIkq%w6Prt&T#0Yz`XSEDvBaffR5`F!u3tn`uZXzo!D5}z#TvIQ^4B) zi~Xk_#@^*USPx9I04hmzwSogB?;-w8GWriSvqKjs&}Rq)10St``Vf$r@A@wQU;bm@ ziysFb{M*1CuLEv>Jxn=*)(V_^41+ZglU<1Ii@=Ld15bVys3xJZq1E8_Y1BO|iefj}x1lSY25`;Q^t} z>q(@FjGeWlmp?^<+z%|I;Gkx0o7{pi5BD@a9Zp%lA~}2J3~o7hHYT+Be2$l1x`5r? zJ#WUN&@?LIWr%|xYSJrwW*_IyQXa9nQG`Dola45%Bgh*s1huKA&S}=NjhoIcC!-G9h9U$w8`i zVJ-M-a!R`PM4}-QC)AE8dXh^pK?=31F$;cnkND>#>zji4`qxcx0izYN(GY8^t7I(Z zh(R!&O>pV*WlZNYa_aMvqE7Y_e{3(T27^SINz4x?*xBBOGX`arLkfY>Xo%5hM7sv1 zz{?SwCHh$8<4Zc#LUIpPj4~R|xX#W#9hDiS(L^wyiCp`XE)pKNFeQlSNXEdujH}YD zg9&i(?sIXxPuzAP1SHE~Z3ARE)NG1_$zdGVr`>g`GL`a5`wv6dPX(2#5S+&$`ooSY z<-Fc>Vg+}eJAv)JL#&Jk9d2t~*YV*bjG5M12v`DBshSmz!fN_qgqP>55F9MP{wPsxe7)mu2(oQ1XNrvJol?y#C zHtu-W4`bz)yKwEvFXNLx`%`EXU~-_Ufi+DW|DgZ|0vK}oz2FJ0kN4<&NRoU?@k_;h zY|^$F1*jUB?gRM%c>L4A)_Gum2V%Sqd*&`ktKl|IgFW{s@c5qs=bvm<7Okbijb^}r z_fUXVz*C=tyz@a|<23Bb322cmT!DmxKNQak#jCb203Ug8t4in`@TE`T+8_KX4lOXT zz=^kf3-0^L_t4ZKS#O0xdt+@44?XxGe&=_77t_ND*49>W#~pX#^r=&5ni@}k?Q7WH z*}-f&!E83gyd?C0J+H8{vxD(yM1a6@5Z8(p4tZWca1py%Yb|u*78=eYV@QU#H6;@S zgk&TR!>om43^LSl{@2``5g=4pCR<^Fz#LUi#NhjtH#BV7!T0 z@LF%Ykyi)`#srEY1HipGlkvbkO8kTkSd=J99O&f9li1wcJOa84jZS(NFXHqsvcr8v zvEjj+p~&o;N-d&H_hX|k*tNH}hrRth6h$5rvlLm(MeS#ObvY%RYk{jD3c+-x9O%)3 z0^b)4N(F)#BZRQzT}8pPi6P3W!(ceV>gqc3q6Dmk@|dQ*y**UZDe3fc4yP4X*4MGM zyW36t&KYQMNK5;Mx@k~Vb4uuvesU=V*4NfCDu=i>y#`xY63)mos(!SJ4~OFkWkKmE z97*k(l7a}sYhK>3 zv2&=wL`F#dM3dh!AonAAfI(Y^S{ph*!g;T1m}U;ska!OO6nsox;~qq_dpO7LTtoT; zhwPQl$vV6;MI zEwn>NPd@;_!nF#AS6_BD6&pFulVK6H=z6hn>P>IMZNIlv_)?8cAkr7vFhwt&xn6c{Waa~3#r z2Ve|!`JPS*lb{NX0-Bme{(&40M&teu{uAJ~*MXnC2l-px3AKEpb0~4nqgc*jG;9Mq zpM!t&SAeHJ+0qktD(t`Khj6t5CK?#ua~Hn(fB7|t!6;%8(rzatg!Q#`6h)2)AACK& z=Uwl@{rBIGrSTX-NbK(I;_=5H$DjS#pW_Q({37=D_o=(r3Q9H5N}*9?JDp{jR|>U+ ze)dJV_Nz#uqGrDMGp$W+Z#0}XHGL+DV+^Cg05{)!2FuG!F=1V~as}JlJIJyeN*NS| z=}7bf%+tx5PB*W0y?_SdCvdgub<}jBLt)+u0J-FBrJ~{N*|XT#*oe(bD0suUcs*KQ zC=SBe_KIS|Uym@tKkoa|_dYH*Qucv!4(HFG$JMPZWHR>+pFo~TXpideH>0mOr?BLV z;DGc+v31rv*0yGKIsrz9f`L{VIT)uLSg8g^w^QZ8U=RU^>2xH^GOVwzVtr$sB&vPW zYK+0&wQD%oKZMLBBpBw#b~H}nRa{?N$7C|0>QHdhYL0{bUDVYa`5=cf8V~}@t7`=0 z@Vk2JT+}Pp(UD0+J$}X*Ea&9P$ASVDiw}M1INcGA(pC(JO9{b5+=+CPe@p923k$&n z7^mus`vfQj(GpEin{$=~ZTw}}y><=z`}^43+>D7NtzM6FjCwUDKF1-(M}q?2@z7n^ zpUknbGU}jfJH>;)O4>N=95k5Lf%Dn&^pywIHD1eGCY7ZDXs_!TP*77SD6;vq)Yl=b+Fc}!FFyP#sGUeSzYFy~<&J*7>p76*&HxK>d>_U>N%oCo3nr| zDakVqJo9Dx$IjCC>bgzzs;0zmTPa#_N&gK9+^0VaJoRV5-c@Ap{4toNjgBV5bwyha zcEGJ85TYEkAD|%zzI_8U40!8*_kUn~+ua>H*`oV%^UY`Q<3ILeICt(G9(=X{dX-%VkZ@iTk1q5Sg6m`sZ-E|l4y#4n0><5|Py}i9iBeh;p z&KQL(%e`u6lN17N1xWV0KvCq-Q4Y8jgb4h9GWp?gs&G`Mfq^k9mRDC-G4xsosTFmI z`5O`C3E!V~|2JZFo-M#Ly&NF$xY$U|ZtHk zQY(;LqN*yW)RY3CMDARC^`LA-V^>a;KgJ_?g{p9G;sbURq+tP>3vcJD&@`@tR_*VE zMJ7>X1(;y4+K}oJ9Hf_=wai!NUV)109y8PyLU$`js!?(i2Y-_)r5C10)9uO^LstItDoh#sU}_V8VfsBpkqqd!DcB z?fTKf0#phRla|jP#{P8$43~j&1Y~(MOo|18(NrYN4}rsLz;k=a8&{G9C+v-{~}I& z``@{t!us^-)A+$3_<@B;a)1n#UjMq+;eq?_$2Y&_&G^zIkKhXre-Y2V@I1D6cA-?` z@kA9E@AC3_vSO^88eCHn72YHa(0*U8I@Y{t(P^}S>5JC`OP%AWb6V2tKppmo47{ihm zk_*#u=Pc&48H~}$r7u)G*gm*Ab`rnL^0?#6@*I=BDfagcXdjYGaOW@pPC>E0E=nw| zj4&FGuyf@qEs_v-8K!bA)mbZS)N+~oA?YA#qzKp9^t^lun?ZQAh4xG2>dxOx= zA|}A%bwL2|c(WuajurYzEALEl>{SNFI&h{@HwH?}sD5YR=o)$cF|37lw32a*!7=Uy zNvLyo&S5z#aB_XAlY|*8xHYg!g9}NX;*LXs?0z}(hH{RIjToSCUc28vAk05xMg!b{ zG2x|8Xr0^lV5%Dfr-^zbTm~Lk1VR8ZgEbD5xrWh}vTE;I-AHnOIiK+xx!?WRC~vtF zZ~kxoDL(fv{(HRi#m5K_kyGQ{Ik*_GB7rqY|6LNKR<}$t8OR+_+NARjG{AH!-~gBj zFrNT}5inRGil4J>qLvx`0HH9@4R!hR2~ZsZvwfi6CtEyfZ-A_%&b%Dc>v7&@jd}|F z`M&|)`uBj-cXX0&f3*`QDr+|Z5C0+XzMllP8yr@^b93NA4eV&(!JqygaP!~$&u;j- z_i-J4Y3%g<@3{ST+;;1&c-!0FhClkmC-A$!_hD>#43qZL4atMkq$J%4ze6|PewwJL zG|jY@!&nWgHFfxYG7z5MuoiI6BFhIT%K_$fjSCkq;nc}fD2f6vyzl}pU%rGqFQS7f zyaSvuAxY}ky{FG(5b>e)C-+lC2`O`88R(`nR&E7onD@&tiQpE4lsRs@?RMOM|NRls zzlce+h%$R4UoRUQ3kvH+`}$Y<#W}~V={9%lNaSj_RD=4#!?zwZ2#$s=G z7uT-sMx0hCgo`r&XGao$E+v%H5H7?2&)k~^X?C6GVb59az2DN?EZsf(05iZ~nE^>q zq(o9QDTx%NP?2QIDp4g-ic(f&*_N_6Rf$s-rBaULIF<6>xSXiu(l0rRD~cmkLQ|A1 zkN}s#02pE)0E1b3-}~F{y=Tjh_nh;c@9XZtfCNBwX^POybWiua=ic{ypZ8gWq# zEieZ0b1sm}3^L0g1xaPB&3*2*LG5>Vdt!S*@xQjVXf|7rLcmxD=SVuTw6KKBm!HMo z`0Qs7bfFq&kB5nG{4nqL(Cn8IHtOXs4=hUi1!HjUiEphX_}m&I*;$90F|e#aCUZ10 z2|%JY4p!F`!sA1F7#DDkaCz$-gv>BGkwI&P_03I8w%f>y0=vBm!qzaF9LSi+sF|=t z+!KOBGM~<8yiA6XoipR4zYkEGwj8yWf(qv-ZO7_*C=a^M$Yf6c&9tlG=L}Q`N#Fy-EKGjIfcR8-`P0z<39r?b9DZzFXPbZhfqw- zpmFFZ7M_0^-Q~L|I~LXfTZ-amI|i5%)Bp@DP5lgn3`}R#6fk(HAc!jv+5HMY=?k(N zkauw2@FqVQARAQtxfqfFt1d9u1yqj;zDZ4l93TfkL9B8@3(SxQ;4E`}&~ilkIo#5qT+)f&0ZB$=aiZ@b+dK|0^@Y#h)~??>i) zH)msKX9sug+y?in;w;O^mC-q9qvHPl`>841IXFcFvyd5>VJKBOl{*fE1tiFBu z@;};B_=OaI7smZdt2HDi&;H%cE_OQ|G8xbcIxoPvz|71v91Ln}iPi0y_~Y;h1-kec zN5e*5+<~lDSJeod5{MDO-#@+BL-r)eV35G_0p=KCQZhzbTh5`a&!Tq3JR5Yo=<}qT zsI6zma(`_c8rbY< zl*)`;w{er5@xY4!kBt+B%CZ~@2nj|ZVfq-~Ti(-38NmFHdm;K;0$CU*tg6B` z{R;)>*6lm^=ChZvyW2sQ<&lS!4lb!hZ>sGkxmq2kRv~13zlF0gE-8!I6;`9FYIJrx zcw61X!pagaZ0KEoYEykHb;>B}Tmy zVQfE^>b=Ni0ISuPzs4cvS@-+84Ajw?~zmT9cOToT)MP%sA@9Tv8sZq2Y@k{ z$R{v+sEx^q3DVbhOKk4e(4YXFpbIvJ!$6S-fUZ5UiGv9l*A`L`iWATV?cA_&0Kr)F z&@<#?-rvUirkk;BfN;!m!BGR)=owUrUw|Oi7XWNuv<*mHunm= z89y6LX1MUBzk}sx{sN27`~@EQ<=;f>hn)y@$ysHc=Hu>R#wrk zfqn%nhwsZ<|7MKp_oM)3BrxNsSx^qpf~pHpaQ@QAa{l)K`B2VB@CwKK;f4L zMd%3&!{EI+qax{o1TwiZ|qqTAuE3B9NK~gTWqitNqyfWm%%Cs<=-N z4uMggZaq?-TGS_el`ymjpB||DHAH4HF)@K=vl$1*vaYeSy^VgiOYdIafQ@rR zM(!*ZWViz6zy(LQvy1ih4Pq14HG2L)&d$w6`@ob)k>@#?v#2^kFUARR{fK+Ph$6uEsYy?Oo5pQ+#|bSd{GYl2-Y=^>eB9Znu-5na z&(5K*hFpOZSqKEY+BgUvjF;$T!5IgWIdTAk89e^LJWd>)jGwP8$4+HY>#(;ZCTpvZ z5KN*n4yDp?M#sbN44M5nM;_C;V9>l6A>A>NL4v`G3>mXzEo_G`(aDK6CR+uJ({PUB zfSWl-#u&79=qd}NYV7uERN9S90F6cijYebNhAg~n_Cr^i&E`G5!tW(FI_PXT#&Gy! zpGNE4qfmoBgojj5fBJKnee@EZ{GH#!TmRP|qT1fXoB!`0W8wMBkqe-mPgn#XExb!1 zl>x=6@Yg=Ce$pj!z%)-h4f#nMgpd;;lO{p$A&-y70*l<|17v_wz?H9{@!%714?j7) z&TP1=RK~zneYF1SkAQFdKh*F$Ku-!>{N4Wr7rykH$P&nSza+s>#KW@^I5h7>EF1qj zw{G9YtFOIAaBt4YLDD;UR&@;n18(7iR!n^NSTA{W&cS$gTyW@%14MGpq~`(9s>_Wi zmdNJT#e(ht963A(fTMO6YjzoWXA5dD@RrXuLjFT(s)3X|>DGwhPyfD!bHVA38h+=7 zyL^@y%veh?#(6Gr`0!!0+ilFu%%IU|j7;`vW1K!?q3G-f;im)7_~!!lb+T-kqt6#Xd(i0sN`K0S&001BWNkluuwu&Jv!zO#WD1WvF z(1;C$V1lF#f?S&@JDaAGg@r{dE-mB3AO6t3FZOUS(`h1=ca0}djT4bl$T@t@{V>b- zbI%%726s10?AGM5;GBoXyrhQ-8K-~e4Sbk$FphbD>0yT(Vjd?N1L%V+%K$+>j7hl1j_|Un3Z#IweqmBgY;e$ zjuVigje$}WPILU!8MLRSv9Yv-)s-c5cXnV5*|0jFE*f}HN;yyFBMD$2safwNn8N)b zfQPYA{F#USy?4me6fRzT9H&p89)b2#baB7ueGQ;lHHnz96&?*|p zGD)jgWiWf}7^bJE(e3t;Wm$x^)9yq{86$1A-+Kg0L$Z%07>f%YgLvZK8Q&)*Y<|WV zv{ErzH_tP0#-hD%knuEHzH2ou5;Nk9E|XBI26qB1ctmSr_b)CiV0~?U&p{9S$D%0W z4mu=1g&kHpVWx$kD2fp?kJLUkmFT5KB#=4oC0prL23y?<);i>VhoiY5e`)9Tc_~_e zaWLzkKxul`IXI&znNQakSm|ZkHj;RhqKOFBz;T~YrWLl0iBY)-`$W!t6tI9!!gH+G z#0JtIc~aB*$QT7@Ei71^R-)@6XRsD9b%}x9gw+aJW5PrCR6H#MI^|xD$vAA7UiWbV zUz&YzKdj{M>ueYU2L@G^$UOuqnv@ZK_|Yfu(9irb4xfJI4OaaOZN4JpU|!Lus~AKwdVuq1PvJXg30`^FjyMr8H6CB zpYe9S&H;b)Pk@I%4*bX$Q9t}c5Hdr4`&Hl@{|5N8e-5kz*9So7u_y8H@BB|V{K=mH z8$-&*t(DXJmIe!rKP&G<1ar>e({P9<^`A~!dB2$D`Q~2XS%h{QyT<2n)zg8`L9Rh4nlFNz$DaVS;6IT58Gd&y-SGcz+ddGh3*_ssbJABcVjvF$@} z&vc^k$#aSW3aZCLA75R#+c?_*I^FT%^d82>XjtEEBZ=INPJUKHII(Xi3SA(Bs5F zKVPLSR<`>ns~Sa4fgy}B6cSWGeRjRIE;{ltuf5|Iu+G34H8f`d1wUBpM$B$FH|X|j z7-u1vj4vQ#6fDT8Di>@dU9ay&?$s?FJvXnray>$loI;JKlk094a@lOYzQ$Vz-bLI zhS`sP64U1&#pIcDn0)vWCQhEg`m;}C;hC@E(8HI|I5LOj%THnZ#x<1Beiajzd;kOk zlm#-CF#Sb6ocj0jx<)+#LQ}vKG{7eR9UdcD`d^+nn6-ht1uVS*bhl9SyTI}d;Q#o? zz}+RF1ePb;$ba#-@W_|{A)3cdja=9LB$r`|8@EVKC1t5hHjv5oQ_$?}?BJExuK8VW z233=!tyZLw9!A`9I@8X9`zd}j=2;-~hCOvv$7tSA$Yr!rCF@kdDLKzL2dgP#JrkA` zQhxn5URd)yL!(ik-EL!YatenJAI9e9I_h4}Py7;tK@YuNAJ!5X4B*J~0!5LdC~}k~ zDKWyXAIRZc?H}{uv(9|5+VnKp9k<)d1)DM z-+Y^lbU4Y&>$(D@q-M_SP5k@5YKpdF-=~eWE${;px<*oeyuylcSnT!ZALqe2Ftl4O z%+AlD*=|R4$5@Ajg$1lEtqddXJ^DDlz8oq1jYa`&EPP@hB$rrSTg9D)yO@}sg4KQ} z)M((;@soJz#aC$O>km+#=V-NPa_RT`D9bViRxpef?@$mz+EtM6k)N?i8iY|>$}~|a zG!VgC84ToTt(eaFYOVYheQcQ0qsPLQG zLaPeSD8IAh$T@jIS2blcTR3n@d#~w&LGV$ufia*vP(FKsA~r^%I!0jN|BRcmO?<8>+|$7HL4PFaHs36VFzg#;5E za2{Q-8XKJogG!^wh93OkzU+4|!nLJX(`=6>JcS_-dI7zsXQQT|6(%#V_7w6)3&-Y9 zQS;y&W`6jyn0)X8X3kxJ5CUgE|Fh^W-ofgh`~j-}{hy*CJR#o~@l0bpD{B8V-MTr^wc5DAD@p0FBENSN%Ncr3IG7N!@?gRXW?OgN(&V z#=Me6q6E;&?y)?icv!MAqo@e*N*!2~+C`#N~#M`&L(@)Xt~hCD606s5Hg$I&Z5m}YeSE#Wda+0 zlJo_yfUsXolNQIXZD1ddKVbK(H-1mgM$v%C$h%;_vmu25o0*~K$6AOi$K>e;aYq|0 z7&7TQB7q4>(|H-8K>hYleZ5>>6x z$P4UtcCfj%2@Z~&N!VI?3zVh;XA%>WQ#gL&BtctF zKr#*?$rIW+%2nr#q1|rN%g|Q&z;Uo$yY?kOLKxRcW(P4~HA+Gu`T2a7AMn*2=%x9r> z1!HPB>m8%GAh_LH%(R<0GCj(M9@K^$t-xTk0?-F@O`80zL#-$T$PfGM_{xz?{WEF&K=(>5Yt|mGhBlL~>71GR!ld8MgWc17$H$uvqjD z^6(yK0f)&vyu9wmo;00W-mA00_$b3=zq7%D?<&Z8bmy&Cu~`8|3{KFKE}!hr=!OQAWXmkk<6U!rG#z5)7{{w`-j;y(aPKX42W{Niup+~599H_I6DUufzd>i&bJFa0l_l9`zqoH=tAb8~b1HdEsXc?bRe{X8?N z3T!`8=X-fJthKm#;|8=gUSTEUGg=#B+4DSq&uU6QeZrrmrcbe9^d!vjf*x%0xgbry zWdKVQLV*-2Gf5^*b%ojKY0S>eAHGOM*zSg#;Lf_N$Z|wJR?#Dih zCw}Gc;oN`trFV5Lf&?olB2tp@et$oWQ%=_>L(-c@UDtT++BLj+{jJF6cFvJatM#O@ zgu5ZV5swPwypX;pgfFBfPGrM~XhlWd7??5W-X~hbtamro)CI_&Ge$kwK5C#4_+pHK z_19u@dIsk%JcfzsDXiYPgYM4u2vImlGC0qW=iJNHh7G__&rLZZ4?T1N4?XnI2-z-e zJky3XjU*2Z^gHnZVr(&gXIIVl@@%ZFuHv~X&-$>VBCbnggs($1+j%c)N+7HoWk=RO zOi`aJc~k)eRhxAd)-o_DW1vnruaq8X!2IXT&Qf&ppx1-3290JD+Z$V0TV8|K z7EEx;;j#)RkDtck;^Msv|LlolSiEzW*xNAZ_xe~~S;6kkE}E?-8S+Shxg)c9@PP+$ z=gu8SnZfvORrvVIbcf@-QI54HUWn8z!TI8z24fubAvq=NrOs+WCpq3g#7ZHDm=VY3D5jpshi7XA|Fi<{S9cU-=cx&mTK*;=30Ed}J?^W#qaP0(O#@Rr)#o ze&3UI2-0da8WBd@W1q><8+vcJ(ExNr5Rb38qrX6YEjpqzNNJ5G%y)bF|XK+qN4*?+rn0K!-x*Ec=5$^DcQ0VYmgNa6D~ zH#gDkc5(dp@%z62@AcVe(8BAb}Pv7h^OJpSe@xc0C9Io9f-<6n6H(4*c^(g% zh69rv8>?$rURuKWhc6IRtTdz)IC0`QZr{F*q9~xWg3=V?lEQ962ruzU9I&{9fb`v& z0r#>p>(PPX%@(mhb1u+mHc{jmv@z&*x^V{=AeDd)FvcQT0|1OOaJ3zQR?_a5`OIsr z6`Z1?wX(d7_4W0U!e3QYgo#s&NVd<8Zk)kCIXU@`FlD>lj`Bzz9hX?#Ri_Vw(iY7k zqnm3TDs4~)25PWGHah;C%scAwIC=YtT1aGh3(jarZj*ghKp7ku9Ljo#6fiExl9ziY zKVRI9%c31{N_5M;=D#+M_Nk1bDHsdUq7sq|oI800Q>`MBggEEWPN3bC$hZV6TF8qw z?fJ8zM}c7srFK~Fs1Yeo8o8Us8>brn@OQ=wZd&})rt8-2J6Ky^$L#Fv2n_#0o(%y9 zr!`DfqPq576o+R~w^~^5^x+A~(ebY-frf7iOAAzHnD3Ku(*9eI7U3Uv3F(Hj5uD*tl4h1=SXf%ZbI(7I zwe@vKNs>Wb*RX~npabV3>~cfsN+^s0Y7Yr}DZ-G#^1)_X*BV+W)U|>&h6rJtng%$4 z6`s82A^*s$PmF+u*NWh7_}>rQfRIY5je)Txq{uLT{3I-Zm4!RlSYL;=23f`v*HG?x z07#&I8YQ%5s34H*aEYZZ4*crUiGrsHc3Ez*kDIO?Xbi=Z@!^d{Ad&ZDS2P zJKMC~QsfyENR>u&I7L6pdtFmTn@g7%^Z24KC)DfGKNY;J5s-M~?i@?^yUJTWwh5V8W>Bn}@v>S43Qu`TKHvMdMZ9{N{$LcZuMw4NU#pM;;ymcEF9)4(qx&J|(4dZuzjB{N7U;jH?fBu_TUmX_xu&37!=-2mJ zy58U9#fRizJoLGrz~f)~yEyszpBo|Yrm7W}*xrU~7Z8{IcEO=oyqlQhK$Hy$o8kU# zZ|~x-p87i8eDgY-CGCBdSq#bny8V8X&IZn7s@w?h{!sN%Qx*k=QN1=%;)I4mshaF@ zbs(oP7;fkt<%oRC3Qj~~A&~8}Mxv%eBFi(#Op?!lmlJaDo#DJnz*-A!6l780)R{AA zG#gM_VS9TE+)*9|9i5QeM=*Z~>!EcL746qwe+~cc-!)O!H6D575zNoeM`hNyZEv`@ zX)~P?QO9`}>3i#gJR6*Itgf!obM3DK=fV7k9QL%gzkIK2N*GjwDlIMg;pbLLM<>A0 zWCUqnijb!YmEoDx;Ev(gv16Ep&W8wez zUw?`nnw)gbab#SguliVBS;6+!790brszz4in3|fx*)wM_7?cs-PY*L44n~tuU5^xX z#{lj%HIiq@iwv2S(J&#n8^s-m-;dOZcR%9{nTN;HEai}{l-`8&LZ=6hc^4-}m|B#- zG+?2$!kcftflqwuQ*n};n3xzL4;>Ufky^s;_tH1YWE_}i7La0SxjEU&p&X+r-5P)~ zI7^esz_Fo9g3-z(g#S>irGYWD5^#+EP9`}OCJiua0m0ymMpafQ2Nj%aBrgw!cB_Ch z3aU>r(M59-x+q|cgE9v2@a*07E|xY5oSB;%*;yV0y{FD(2l>RO7QKuyoH%g;Z@u+4 zp8ERJ$ny+yv$G%g+2GzJ2mt1O=GQQoKZoAezk)+D$MS1$A#YL=@AvZIZyx|)>i9H@ z_7qx&=W*XAXIzejvHf~r;s=d;^yMFK$oxu6d*d&yG&lz)C#TRT z3iSGYA}2GFB$H%JkWbRs85_FL8K@e`y{6~W7#-c?Vgu{RV@zh4J$@3(S!CC*V|!=Q zbF)*oKSB&i=il&_)_Dx7x_R>kzVem-4==s+A|8D396t83kKv(*9@=-`o*E{NTll8U z^AGZDY;JGi*~{O7loG90(-%-NbUoA>R=qzp1>9TsY8$Z~F~ZeR(WNiAM9M6Kvo3x; z#)mw)arrj~aCr6zPMta(JsXVH*xcH}?K^kS>2%<%fnbu(jNTu*J7C=K)pZo12~UP+N^gUU(+!keyjo6a5$Gy zFp5@@l`4h6%wz+Zee<6?WT6D<1F&=2B6#R;_8bp;f0r8 zA}$0Y!xn0^%*ZnojS|oI}RAYa8Dy&N&!I7S`JM$zLfPJ9Z4e{7b)x zk3RV%UVZ%c;? zG)|s88Sf97dGU7)5&J=(jpd~!tgfs=Ddj((`rKM%`x*ZfbSwGfwg^9@tJb3OLwzk&MXcdthLuL}gI9--VV}daPk9u@B zLOL1#@MeVlDk5Xkj*v&V6yOj*O%QenLrC{4fsGry05}^GVVGdZg&>w?=H1r3?d|H) zIyN^qaQ5s2&|0G`OR`M#4^2pO3pSJo8C)FX-#+d!o$6S_fe#j#;X%kUf^i^n3P5pz zjVdEytFjJ85nG-fI6=0MGN(zNGgv9S>mnfrB5z=BvVo)16MMe@W-c(@kl3n;Ct!_& zGiH=Oz<6xluveI}001BWNkl;tT?Ntn=m7_a=eHg}R>Q}mxzh8*?)X9?&Lf|{k zy?`^P&)|^@5C34#1{28IQ#k&kpCdT_=f4bX3_7>p#??e= z2y_>3>hWlAo6~6o8i+J|=7qGFpMY-gj0bZ6R24#t|s-S8W!&Gd_yYTO% z)N4JsijL^eoujXo{{z0RHtw?-s{el5T}p-*cCDRRus%|kFi8;#xFT{xp- zDA{08qSxz3Qry(k6d9Na8Q&|60cF|8tFOL-wY3$TI&}t*Jn{&^%5!t~+^_$2Ivdws ze-(>MOMcSNyfKi8n|BT%dmn2GZCpJ9!MT6ec~qw$B4}MJ7-wSOQ*d&0Z10*csE&%F zfYk==RvXh3lW@jRlgI^jcXzR|u}%m(Ks8MstUB8F$)25^!}97P8hHbjQI7QX<~I8M zK90@LLHTK9Zgvi5&z#2M;_W>asUsbr_Xikez;{o;A4+a85Y$M;-;KobZ|1QQE%2O27YaYE38vKG!uKoG2GIT?LuYv7#!-WVXc zAoYfq#LYA$+Ks)%NeYI^f?;z|!*S-n9`{7Q6dhpEjD+ZW1ntvAHH456c9xEG&75&q zFw}-a$|B0-LSb$-3*?-EIWM(~6I(Dfa&QdjR2DmZhe26`!;VbZX+C=@iM!vuVfu0C z&r3S+UmQjh9}=cbw2jr(iSAN0}fbkXhgMp*KU^9a8NRZ*O>0Vp51!@Rjp3Zap|e;waF)F3!qeC#p& z^cTK>xw*OcJr{Y7jn!4$x_KSV_5=S$OMXQBe<}t;O8UY>$9_OX6G5_69 z|H|+9ol{W`NYAf^lo@8{kHct#+qd3EcY8DPY^+86?@(X?1}V9}FAd)i6M<}Xbp^Y- z9jvS@XJ5| zbDuU!&bhe03uhyI&37{ijyEi6gSKCTv)|e#d_Q;Y-o?-o?&RMue1T zG@HY8y|HU5#tLig34PALKLQG%jiHo2PvA4j0MjfQ_|%Vn5+DB1ha$rB>Z`BfU;pbr z!pkqe2*DVtUJt9~9c-?jtWHm;abQrIkb_jd5SYaw@r`!vlok0x8%@@{!M~dmB#y8<)3lQeyLiS#!T}iiFKCuQd%i_*$)YaWLUJm+;FX_( zy!Ep1e%U^IoH34Ec=oDwu+iPh#w0P$xhHrI`3C^Qw&tj`+Y57L9GM{GLW&GLE5N0Q z9s$fhtF^Ycy*|J|Pvf}1U+GIH(Nn&1Vh>}j*>Dfqm2?u@sgBq5A zYTQqQlU~E{-#2dF!c$*=8h4kM$z+F71gbHHG9SE|)F|>|#)<{^Qmtgt4=YArY^=3# z9^yCJc(*=^wdF$K)1Ub?e(Lj|$IQ$OthHEKS;5m!KaE#jc?FF|6G~BPo-qn$pfM=> z==Hh~VhPP=8_iY=veCrk^fV^glgOJ*&xNvZOn@_r)P{9YaWjGj2~rG@F9t)w1XIV*7^p(IWm!XSsV8e-U@@kQ074R@VH;m)__|+!hsBh!X>)%loV4GIqiI{Ap`+HE;9;b(1!LX$xSY@0#4Ed z1nbD0AxJeO?L;`^;M~yw%NQ0G7x3C^ui(iipB!OXr*K!;J?#hC9`q4R8G_a|L`w#@ zzKX1gZ=e1-t?r@K)*73Ohg)) zK(h$;zGU$$*-&Z*_~>5a@bY38w>L_hI?{Z{z2kmHQCXJ7$tCzFj6?HbQa^d>B;LMt z3!P2}S6_MwGt<-f&=Z$NivI_FHqxf%e$7(?85aPSS6A`!%de12+|(pyrlv79If+Jt zRxtY^6lo4Y8a$Qy7^J__i0b>j9s$h=|MrcWH}UN&&tY+O*-L^6-mj`EnjKYM<8OQs zlbM7yJj(O{Kr@4~D&y{7W*PFL5h4FtDOjyZ?xocTIn7#&i;p~tU;LXtkB82mj|kC~ zD_8L6fBsdhudiZiYLcRUO^8Rds49hipEA>RU8CRcLdp!=8|$PiZ?;er4dg`wd80rs zC4`hQ#~~ARCPbbi&-{+u4at8zBb4j->9Z)c!p_bPOgSL0kGg`C!Xvp1#`MwccCfXT zqtR%f*=(ZGXrkF{q1|p`Vq(H)xjS?^9c*oFVsUX1Z@h60mo7blix)4(#`3Sj*|>c9 zGJ5?!GASwQ+Zsv)#W1!)^7p@{1kZjjj0~?K1W0SO|MSa1o&@&1Q?(Vp&2uW4x=;Zy}QCcJ9`+NP7fjMq1*4`&ca=6Y;R+F zY8qu#A{P>K^K&>lH;cQA3qFgSy3ve_NcPj-CYB{+Jt;*bLpVpwRg&}7d&muRQHDO# z!PnS1hpH||)&c`X#uY`8qt$M~I*Y2TsH0+x!Y&v`zu)r#8FUz|u`ryzjuRYNQBc~M zG5FTEzJ-r`uNB}7+1Sd=TSH1;*hSR5 zM`(%*`sHExAhnCx1(qIy-9d>;**%`ujUvNjy9FU~fJ-o$LC6eDWO0J$amS`HC<%R# zT!2e~LI@cDpfR8F;y8u;I7W_s+9=q1fU;71u2-v(W3rjS)FmlRoJHRnWQ`VDnSkUB zjyXuqpp3)q^%5U@&?3+H$fPpRF>e`;z9bzSdi4pMSmyWPfvs(Idg`YcxhttU8aSP;BW*M$kS(bR~`rCNnrI&E$ z_8kwiTGYPicY9rwgA$ce5#ArNz7td=MufYeK~7@yWP^>W)=)}A>zcIn*1&mR{Mn;N z@Wub&i}>(|J~UL@Y;NMpl`FV@{VflxH$41H>3LO^_;Uy<=G5pJxIrJCoh@p-vjQ^9 z&}cTj{+~ng3`l~fX!Yd%C>VnPp%h%^BvqCIx-5x>ZXGCw#YM7k;PzCN0b?ZwgA#+m z0F6cityT$ZC;js+eesr_pjTmccL$wL7oAQQCr_Thi4!Lxzadp4eUN9Psw#Z#YhMEw z9L>Dp-_aV@)UdTC|B?|j@%^nSq2LEMKfwfeHslkGdW;Bf-lJgIaHS9wPgWVvFPg%M z6DKGo+sAlsZfxMr?b|2^r60ODYNK)D#BtnNyz}k~|FL7ou)F&PI0v$fqd(~3*6rKa z?Q}3dH;=NeAoCnY=VmcGJ4+YJ-^}QU#s#dizT2X!Au?ROk4~-7-jbl zA-Ul7FZ~Nq`>=&^DTD>FdNWTd6r4jDjdC!ENl7A;BYDhBun6G*JQhl86#nur{}R9b z+rPc9FLfFrnNCkBB)K2Nb*~_q1N~ME9hj*?;MjBqm&dFHGt#rMNW{GU1>;3PMmozM%FojXl;x|uh&IY4Up#W z%%0Wp`&mQ9}&~CNitVQmJfi?e( z4$6T?8|i00e)8mbTzQvJ|Di*Nl7~gWm>NqQn82!-tRH!3WQwF){h zr{S58L~_x=tu7WdDrVLgXwU<{cxNPi`5@ z)><|efA7!toZtWLbar~*_kCS2LRK>|@df^w9GeiBXnYzV{di+5CbTH&^F%Nu3}%OC z_##(CRMasfYs68$(0fqD22_q_xhnD9P2?j>~JD#(h z2}iQ?wKH&dYhLI)@~5B>mR8$&4M*Qu-|mPn&%kAa+wg2N>yzJ}8AQ+D2D;#rnlO#i zcclfLK?25iqdhQr9=>l0ysn1;TGiTcF%^R#z%65;szv_-edgWu*Sl-w{9>;`mV9*~ zuPl=1o+{>L;lO77@T7L$vxTYe)eY>3*ol(sL?aOKi>|an z=weS%5>i$WDdv&iC31Xw2syVZjFZn>=L#lI*a$4I4XyQ}yaS*#G&C^6BpsgD^c^;O z3@iczp?RIV6X*(_Fj$Q`BLJua{me09rsL)e_pa0EZd@eCFHxqHUkWXcG#kAAm}B12 z*OKQPDNF1L+RHJZ`3dn0fxrDwRXc5R#@01?Z-DUIv1Ii1lSLAAyto!_1O@;*j7+V! zHEfhml-IBCukHwLo z=ZQwIcIY`eI?mQcvdgh^1&C#_vD+75bdnlf_Fc+BqyN1^r$(2Y+;xSzb+k?#3RoYN zRS@6Q13r(9O6(q^%o00CDf1YM2-!gizW=T9l(7AjkmAgVlNO+4Z5K1v zGsY|tBix!vZN@IXeTteY@^zO+E*K1VE)!*lke-Rei#|l(Z=tap%E>o6#x~xWHHzU?AOESg*ckV>C)-WZ z%3mTBlu^qs{w^m-$_|RHG;1J|o}$tFD8_!2F#-6|pEq@v+A9~80m?mg)D#h7fQA8% zs&Xs%^&Jklpl8s9uVD)Mo{fZV^C#Z@**CfaiM2KQ->;$z_^!To>)2Qr?xia`zoh&a z5#<5Q{da&8uez>}OiO5*pX&xHyh^HVU9w_f_~8OgKLHN-@FI|pW-e3I6YB6sue9l*=_lqq_}fG{VtFEFa7m`I4zfFrN9p`|5uaglqYCjh_j z3CI|^8blwpIeZf!KJMH(xt;0PgSKXY3!fL|%$W}1Aoo?mERqR1D&S1Mf{vj1O%Vaf zZ?lU6jg1oaMfc?0e4uoRXkj7E_aH^KTNY{XU*plenHm%1JH7 zKpBB7Z>7(Oymd}+=z>N`mn=8}(6E)w&B!I9^SphzuGmGR`4ysS%C|Rk<#1z~u+4eX z(rVcOp7|1T8Xao>(_bxUh$hqgsh8&(d4os!B3?-3K-7Bh{e49PkjLm<9V=4`9v>kp z2;OCEq#CurXZ<>3a~L!|;yWiA(^pTdxETUJ@D`T+}a9nBFYFNn=^=RVjb=0_tjYV@Vw54{aNFm8C!_>B% z_6rJ2Xw~s}xHP{#&*V!jEyUDEbhVgHRQN!m}JKF!&3sp1R` zY;SE1ELP8yF02lZi~wi3GeR;Nt>?21b>I)3%uJ=K z)BNtHKnt0qk5nNJXQrkb-rz@JE81=&8bGAL9&3sxapIR>Phig~$QiiaA5F0$Jjwa= z4zMT88+sHO5YQwZsx2eHx7^U&ebfu;Y68s1(m``^SW@ z^AnwjjT%DO{R7a|O}&hPslY_u9O@|5%5nCGecrY{VzCOP{}oTniCO8@7{6zWg`GZH z{|1AA!$h7WXRL=NMWeKc@n=oQ&S06yXh?6v$_g;a;(o{gT#AKlnE3+ziD#U)}m>)OW2GEPeXu^0jojCH-w z{xsIoUD{u$Yp<1yH;q5*uU~Y?2GxZ!tQ|@bO;SO7XUqc8e01RKpQVhJjvzAmaDrowfD! zKaRq#4Sp){*a}2PP2E$a_Qpjh=`!gAGKrK5*+NZT_wa#KKQ4$}@w{ounN6mXb{LTz zVy3qfnowbNp<2o~35XFoScPMC{EDx_9k7^D5J+-%$yVcZ82ZGvMkh$RYzBH0{kn)3 z7q12Z-ngqU!~~@jw2~D~z!*auvyTuSF8LthzK;6?&oAc(0Xg|-ivwp?e*SPcx=4&x zwf3fFOYmCDT;X5Fa@T_~Ohsj7DkLh1c(LgpxwCG_0v{Fe4AN%FpAZ{`U~M)QBq1rj zXp{xEBcYXKVE-s8GM8tv^h@MRZ17w7bXjEEEDj(7zklNbz;>azr}~rPk386Oc1Uu(FvJP6Up#*3wDHp7goyjXi;H)W82O6Jj#p;0^OoymW}91 zuCiwqBm0r9`WBwKg_8>#N{9cM03sd@UzZ!_x#K%eMDrhxa6Cw;376IvB2LuUa?N6G zN=lTY?F$%}4e?Z~Y+3$Mx3j>;32|MA1m%i-25;7)wvCAng}AJ>m&7*u0qJwBMQPd#}Ua__*DO@~s!zx}d*t z&$>C5yWFz=M3PSG%sKrkt#(joz;HO6m^nz89ASUaf|Y0crFyZXR;D_VnAdsd_i9sC zkI0u_>f-0qh72_F0K5^#^(Do6$cNR@XVl9tZzrMp_lDm-j#U00wNDlVL>xQLT2-4o z(!+SG8IX!}(e+67dVACtE!^eva{Aw0-Ted*<(EAct<^VTmTv#A1t?b#xZ%IagQA;? zwL9-RRZ$4sG(D^Qt!Li=F+x2u$Odr~f-z}e{U!TZyT|j~T!r_{TRQKbE-ypH&``_6 zgeg~a4P!8^JiPpTgO>e4Xo_B@xm_h>IoBRvBNsT%=OZ_#Gfc(;k=J^}!b$_}X zfb(8qM68@XagIwj>2(Kc12aqWHMdj1$;ca6ACLBhW|g#1*?H#j37*9cw)ZD?^W$@Q zo06dWQqPjErmp8}E_Ynn+iq~7?!l@ecEcR2zL z&yE7|9ei_oi3p)6Mik}1C(5#P;pjRGwhe__VH8R9bWaHeyPRjquN`<-vRYYI{dgem zi>)R^pG)JUK0$vX8LQbi+n7+?B{hz4_RzY!-8*bPA#5>S|3VHtEF1*O%Dcj9?F4q! zV|yFUX*Gn<5D(Yg_(cDso{gCTXe@%=nyxmOXf$YBNlsoH<}%dSxUwqb4Y!P0RqlZm z*ZeF5*ihZ}!#iXbYQ?c2ZHR>g6y8kr8bYK%gN@Mj4dK7Co7)POWhT3|im37X1l2lq zBR$a<{Y;`Sgv$9M3AAmj@gr9|7?TP7-Ckz|WvT5)wO#MOmSp-S3ZdURSQT=9tTZ?g z_defU?ri+K1!UMXwTepmA|8t3lqXs?UGD!lYNsbn594r+ty{j5ZuY$}L|RFMZ$gc| zy{fgV<*-UljoMuyr@Yq%CixRZXk9_x#QEOv`84-mZR;9#8+c1#yw4g5iWDF?m^L(O zpIWFAKHLMyA-peELXZ01NY7RmP@nZOcTX0pv$FVNwW|?B{8kM*-^V{m%s1L1RZrEu zq4bdybwMsa*>Aym;(PwOEf&kMHyIX$Fi|V2_;R>;fV|9Z{vM#**V|@b>1c}8d#k_H zIO7334UN!${x@0xC107?jG)-K&dk&lypO!cC(*PDzTUqqRj=H62l6sU5{N|?*M2Ua z#_X@uIec%17Y|uo)$4woX4kCJVzYK?wBl_|zb5NT$(pxdE316LaoyIsImMqG2Qj&H zO|eKfX;<$~zxk-=n#jl3>PIS+#-1))&)G6V4xHd^Ky7{Oc@Lb0}Y2@*)40h(FHlw{Hluu#d&*Ec`ig1TuI<5a^j#=V+8QuvBhM zb|Z=`e{=n^Hv6C*68F%A|L{m3t6o`)FYU&$!+~(pf0NM+5=dfTfBwD4f(cKFgl5?5 zikS5Au&>L_^GDR6WBjtNenb2euM@iSYaah3sJZI9!>SBqcq)-i?WB2eS_-C$VdT%> zw%EiE zh3N4|b5m0YHypFqAw*_YZu+@Hs6~Z%`b5*_k-Y&b{d2T1HYt$)F=BFGV$1HI8>^YS zpl{o|#gsKBeP~_IU8wLE8%b>Ou7A$>OY(4AK}5-g(6osp#7m&T&K3v%T3Jz#lHk0( z5oW8l7LLv8&5NCbO2qD$-RO4LYbv61o^(yQTNHVP5}~rLZHb)29+nb zk(P7I4E^CX^{%+oX1<^F?09THHI-ijotQXqbcI`y`d+5$_G7o-orY+YqJZId??06P z>B%iPgsD8`2jV=Jcq)xt>Tm5T{xaU8#=x0W3IZ)K*JGWg`TD{a`8&5<7=N@U zCcQ8hTYXXe9)pDmnW%{6g--kHg&xIiX9rT~<*bQ-gd{?psKp)@q>UW>wokr4bnSK{ zy_>G6xkr%C^|qj5bPWyO0U9RNcOu0hqRLkL|8d%|2k*maqo6FjiXyQKbVF6^fCjP` zY)m2Oqa6=O%t-!C$`i_(afo0dko3r_XBjVP%MMgj-ic`fLZ22e|b0$ohsE{I=5b9T2WV zCUOqfVa%|yGMb3)s27;h%e?o*&)n}@I`!IU3WhiKKSg1k<}S8GDrlB3u2YA`#>on& zkRVazDD|AP@GVA$q?D*?<+O(s*?(ae`Vpp7_42U!)brD9 z*_&UTgHTEXIw83{7F1Jh9d5rkS&mbn`7@0c`$wb{Lr!w3vuTJ`lL)C4?;%y?i6c}E zL1Ro^4mgIDCl18lD8Y~&P+{F%40dMHo{6uN(#s33YLwRP+rWsc`8%FkOlpv zBni4zdc7O|4(1=EI*I|U#9=^zl*7DS{_qYHbb2xm*`;UBIC<+fy4*cW6130GUtX zo}JCc=|PImYBX@%bTsS8Q>nlS>rN{lPd76sFCcgJ;Q%Vm=%xKR+ZFN<=xot9qp(O^ z1I`-9Jzo4GpV7O-wpOGK+C8rO3Y#SQ&Nq;Xn2r2=*?r4XMuU;BzE%zY!!C}?%TvVR zi;?}Y;4Ud>Vlo~=xjNWyHaCjB<~Jq1v$>n<=@zW}ggM*hw$F%mq}FrkG93sKm?KJ( z%ges&g%s6OldV=*%9kQr#0QHW)`qJ~;T!7bj5b(Y7A+i8C~1%g`PR!`yL7b7?Puwf zT=Ca@%WWa&cZZQ-u*`-b#U(M53ZRz9w)BIG-8NKYh!Z*XQ}V~K;@_6wv=pG_5`iY* zYo3!MCe^IgI_q|#tIA-6JopBc?@e4mr)=SFk2Oyp;f68|?K%JHzduX&-8fTW?;d;z z5UYO$uTyJy+-lr1umgrbBjF3VCti{~jC(4VvG8|Cq7!|^uq&W$q<5bt7yxT!lxY~^ z^jM21i}geEi7lnl@UDZV#}TY4YX)=A<1_3C#CScJ95LK2qHcoRrVUxCO9wYP*Yx%& zC?h_EF%fOcuZPl9o}s~3r)VKs+Qz3Q;5SBXt0JwB{xkiiw?yZOK&^d@ql()7%~*Mt zM9JZ72y}@nibe`iYlB%S(7{r9Qbz6QbOQl=E9lH_*bd|tSRBc#Y%J;QHvkKbR0?8~ zo)eDYV>ou(?rme#^8TS^8!LhBzeI{#7G6-K>M2)CnAqSmh;fp!)!jU&e7)5{tZQop zvES=J8HQAntg+}a2Q^un;bfr|k18z;*+@=;4+9Cvde6?70s9ZI;dJBJ1{*ZeC8tYy zkdTSHCN9`an_53~-lMB7{Yy~fkHD~PTg&PR$`2{S>}Y49i@4RRLA?vHb_ohnQxAg< z$)KhN?xZ1u(L~_XNU5Dw*8rOh0I$ZGovk;Gwi!<}Ryu!9hYsjtu3i@e9@_t!rA36? zu#Q*_#ZqZ{&C}O@U8*0R)f1>Ql4rH3b9EU-QQ_UWb@Kyl*ME~=lrvQHVZIjp8Ee9s zpWdlnL@Mxm_PGLyJ_R~%HUA2K_(Vr{J^$tNE`Hw=|Jr$L#b&u(6wUDpp>WGn!ZG?z z?V(9}7}wN_UHXvYp4bl9K4a}q^K^T~p;`!@aDOZE9#b~~#xc}i^+vFN)ra$q>Qf=% z0_zVQW`^UdviOfT7vgL&D-&mu!d(r<9$1y0^jNZeKKlJ8dV$2a7Rt8A> z71}2FgQ7kMA2PL{7IYOe2a`h>2frQpp5HIeIkqs<=Vpo8Oc%VZK<`>We+;6FzPcol zi@wvb+IEPwd7Wx+1k4B*NRsL}=;jrU0)S9Md$ZK@e4gRj>qhlVZQDlJX=}0L={626 zC(1rP)TYo)pLZBz=K<SyZ)AVk7e#6pC@?}&#`#AC>?n^(Ud@-<^XCSbIK zRcQy#fjf$0Hejl3ossxjjOki8{R5ez`r%C5)PnMUo7a{+ZRX-$%_ZW{Zs0c@XoFu&?81T3}6dnP; z!}k`jH5`nYF|$qwkOnb$tS_k~TXo>#jsHxT$VOkQ&A-svY!}1eGx39(RNLWx*f_P{ z#C9j^WfFTDa(5^svqAaq3l@GP8R!jc3pcpug~EB52_}r&vnJy0re$Gb|KblB9x>(4 z@;=Z7Xa6OE30?`Q_KqJP@6YTp4MG@1czAdadIq$sUvMX0@apkQLSxXwc=gi+U~MQF zSw+iQB4V6i027~VWNo`Dx}5~NCbb!zD}YY0zfQyQVbk-yP15eKw>k}an7k43xU4Gf z$cRHp1V7$P@O?d~zijOY{8awB5bU}00VrPa7&FGv4Z-*l6!KW{Ad=yIlh;(O7Dm;& zWx#5GJ>6ho%bPoN`ltKo&vsmpri@zV(I>}jo=>L^pE-1O0F53Af;dmEw)E^=5QJ<> zJqT1lthoi(vr|Mtk!$?P7H!MEg-t*p?&YG(MK8#wFW~?buQ$H94id9^(<*q`I1Jx} zEuPyIxKZ2#rQuUpIX5YbXY`^1v7d?U8DXALn3F7H1Ez1|j1MkkGTdnXTj3mF1G);= zo|KSl2#JUts`{Ka$O!JT`lD1Y>%XvLz7&ebg?XGX(?*m2hzQdSHi2)SN=e~%1_0<; zktOsS0#!UE)WA2e$P(@L4~oE>;wtb`gTP6H?t^j1j83Jd>;4Gpe z^$0(HSan`P&!$QazF$4%^Ld9-R7>`3fqlkcnNXeA!U4`{R<4OyX@e9QM2r4R&25t| z@dT(X=>#c)GQkUgt?Pf=Q(-_3&`b3g%a*H$PU14U!3I2@-E4*#K%z|;g_O%cAF&#P z11^JO7HnqrN6wh%xxzK$!h%vu<^bf>(H|1;Je|GeAp>K7lF8`--bXg$Hs(w{bsr|P zSyIy=chm5XD$g9%ZV7@(&<*12?PV~zL7Vfj*#!x|J3(Fd4N|RP_FcbvEL1Txebm4BHXCr5H$7qGDcE;(Vvr1 z`YN*q{LLxk^O>Z_(*};2B1kg$;P#>PGQ-%T0xpFkDhh*$?)^#E2x7!cz5fUV-IbE> zPOdhQ`R4s#c(~k7s;sO`LVYci(>j|SM4*&LyeHMwYG$73{Px@av5WYi`Nbo9y#aiKAbk$6gXCrvQijz+ zg;_xF$#|76|7D>RgJ76F>Qs_VI#j!9Q99_Mg9j0lqPek^gO(A~0_DGC{@%x)%X_)5 zA9ib{*IS<%IyNXz8Owq$k8gA=*TK$B{4P)KM_~ERtsWO_vd%zGU42M%_ zH2a<{EafHtoS|X0JR2IdEpsVyxV3C?3S&IVh%meZEfRaHIYh+|;=2vTwjZBhwifb! zsw;nyJ%;MouRzXuaj+_Cxx?xe$Dl&9<#9owK!ue1t{&O(LyFKJ2IAg6;`~%b4Uw*R zqu(kUHZN^}YPDJ)%>&Y~GsWDSVeq8bplhvT(EjcD{=d-!@QB2Doi6QObX`6?mTwp{ z!&{heuQ&>#NCJ&U#7V->^u_^iUY2%Ycm&Oq^>cs65aP_ObmV9e>f766xRmNw9CuGz z9CVxfxp^E{LKH}XtsP2@>w;^Z_5KB2u6Dua^0*A#uM!J0W|(0}z>s)+yR~fJ~^?J@xnxx>ol)g0WmR!9wUi^85XEd-&me{dEm^V1Y0{z$12V z19%Sd>RgYvj%XiyO3Hl5q5g94WWFe*;^aXqbU3G0A0((G#%@&t>{BP%HSIKi0!n8{ zPf7~r*MAcxBTX|R-&hPPSb^ zg`);8WYU_IMf%kXKgUA#!XXqHTxa=j{bCrze!;ET{>+mp$AB5%rvlG{F;JlK{`{G> zZ>a~+#Iw~N_|qj&WGW4a3>Me0*PT$O&glGj308bIyyu@R{Cod1g=g_ANd-L;pzPTl zC`aaVT^0v0eMPKc)0YRQ16LYcaP|yXv0!jTAj1yBzCvtvq-sa}<=aFx?;qfakp-lCUIYSXH`{VL*p zM)02%Sq0l;Gg;;KUOsPmgS$$*TA0KonlxG6{9GZi>(OyUu!6NTV?CTXt8UbQy?Cng81SLZ95DPA?jZstSz{$PCV7F)sM)8qS z*A58|tsd4$$}tqOQ=}r1=D^KLgqdR*9D#b;zCP7&q?p)(PkvJFL*?EFzs=)TW#BCA z$r%QyBfx-Ux&c5zU$3G?hfeGI5`hC?w%O^$ODbe_yy2d4b`i@C2mi1Qw9*Ji6!tuL z5E$v^`+Ph3Q$v>pSHyF<2qfqj_a$nTR9UL;+IF2rJqf9+ zqbH65kJHHYby|8}*Q3MSWiy67`P@5{N1+46M0u;z@%(e&Qs$NQz*`zwELvl>`s;rH|bw%~#{r`u=;{;a#gJ|YX`6WO`nV6#^N5_B9dmo#-+r|FJ($1G8(zzszBj+<8i4t3hR^SAPS)*l z(}#M-1JKctjwX@+H!`z}h$KD&hy}n5w_X}OhQN1Kfu$KRk8v^G0TmAxA0357*QP|p z0_4#x0U6oI4u#rVOtgtONE`Uam&Nq9Lx3-;r|s_7UwFYkeu>LL4}kx@M1;%Mi-a#; zskx|&=&A5~)?O#C@Gl+$7;Lt9sdDQhXVu0soISpg9Bzkti&1aQJtSvOJTPoqiCP6a zxA38$k@CmRqK?U%6h}-Uy?VZ2@PkSz{cC6d5gBSo?G%5pe`g;!IC8M1KRh#-Z7x`|g3zbBz>-L(+^Z;d8rK|F2ZO1C+3| zI&ntinp#^&V%(rl9eEsCfL%6o_iA^L55O^HWMvzG%Pu!)*{QJ+z1`ruvZ@pVRDXd; z030BouHOt)&t1q_N*9b7r^Q3^6hN$Ve{lmgo-C*TasSu%5=hrFy_e3k{o$gCTuW~x$jaju=WwH#9PBwJjww*XPr-p)xYPRrW3ZQBsc45k-D<4_e zm!MJ3kl=7>%Yt`_zC--B9_1(5|^r z?k^h`en=MG?i!gkQn=|zKPYJX`4ZLY7FnKXAHgCvG?M;Pza`L0VrG{Yk>a4T@;ef3 z3Iot`YvN0glix^A-M=l-LLNeQ6b2X-aNoCOh_Ye>z@Dci!k{EHpQs=7@=>lSo)}FD zQdoNwMO893RaT3l_hEzA5hplwimBeo3pCm!oJc*%>UlMBJu&8S49Ped`_yh(qUq=6 zfINv*;%3i;bpRu66k-jbDSyn4gVGWQuI1K3(eaz{va7&~R#7a?X1MwpMo~q9V15n=F#u1s*RpIpxVJ~eG|d~aKT&@J#3{ESP_O7#9!8HqIRFl8fQnEHAvI_# z(XTW$GsDza&~e-Q4fAQbVEEupYjSEv4_P0&QqG@is_|kw8vYg|Y+vmAyf{Qw(lgq^JO1M>BI@KfN1+vvG4=@>Sh@{Y^L zgUi)L*XY@b^!F7wet~@8{Gz4OG(1!`Ka<*T6I9^oiDMujyHY0?G~6tpA!A54oG)Fe zI~aZT5H)I<@t;oU@23=c-0*ms_UR1=p4ZKr4cF6N?P{~ZDAbj{VA0;E;m>=!(c~k& zfiLwg+vh9wW<6d>jxU_mFKbUR=CH<|l`jF2kHYLxPzKeDQl$+MTvK!Q+`zbH1?1(M z`uY-7YlCiH;{9-CE@oz#CtMG%%wGFG-s@~zT^b}J;hNLOuo^{JKWrPkT0en2(48QBbdD1mP(^BAU#^!Vag+Hs+cN}|~?;->hj z$shCqgJ>Nmx#RTeT$D>2>h+i?fDidQxo~f4x0aUPO7JGcRzW zGtH!sns+&F>KFKB+S&V@Z$`a1_l2QPE0@sY=n_yfBWmHm+U372dFnJFHPX+@bu}&C z9IbQ)(efmr?hj=UvvGtYQYYcMnlnbZ)x8+ukZe>%5oQXM~l&7t*{A1FnwcydJ$5D!6T595HBuWheYU~9Sa>E0(uldnG?1i zKAR-tz8~*zx_v>yBCl7HuLpFZ;v}OhT|Spe=VwVobGk z(9ijv4=dzV6d$Ip32CEl9!XTf$T5*3L%GK$fe{%qh`|71g|g;^Ro~%xhy>6w7M7L- z0Ot-K8^=UhdH4%RA&m4^ChPb|i$6UZ>-d-sc6zm+f+6!n0*OZKACch|nUI(nMuz=_jB|dqKF+X~I^$D@ji=vt6%qIv~VLa{C{iFQ&v3`zC z303D)H_pY9eA3Ns6d%Is-v9-P?|at|f7Np-lJw@YvDL)GYSh(0I^P`&NW$&&vEiUpT@SlHSk0Hg|VQlML%H{-OcBmcXLdS4QEhhnjf@w|hA z(12{T8`79Va9~dn_~s|Xl1SDS0vDP>cM94O%DMNT1v{Dl-{M@cQr2G+9`o6zBtQ8~ zEuB-I)%_EN{L5lR=-4B5gqA{<$Ztg$2N=yHU}hr+c6Km$oK{gVBW-zdhH4p*46}0v z4(`%31TIGsfwf5J8dx0nI6+V3fp;mvg6!+0=wfn#c> zC42&Y(tU*8O8-k=%9r5NramkrXrRU=Veqmra*q-U6Ec2-I!g;}KP>%WfCFvNdPGoX z+3hH^Kes>>h2Q!+R$jKV#1MDHqWINMiEL)NTzTbVUIrCCFohR3L6+7%lVh}aE)*P1 z4Hi-qJw;KG*V^!dmX@QD(IXed5mS(#H{w2iU0Ri%I0fS;+xTL_Xa)!;gvC0P>s;R2 z8uJNVTyYA2oTG81$O~7`jICd3bPdhT5uu@wfJW-qiw5)K;f0lGevNvi>E^SSEi*S; z&>jq}cU=0R=}*}F!w9IybfKd;qh}Sfa_KbXu;FrPE+VDL&n#wcW{@5px4QN`DP0s* zI2}f;&HBLeaF$&rb{p~Jo?75T^oe!@jUJ8py(^~R?v$Ruph6TsIJ0PhI@Ab zLWxM`FHR1H|NeESQTT9m)pB!Rzjcw^l$80IDnNjpBhNw%tRM;apueks3!caX{STD- z4-}%NrY=0$fEcSQ(Fd8|pDeC)c+maFPIX=O5(7ImxYcRB-g(nMJ|TfJF+U|+EXSJn zdb5ifYUw*c(dd_=FZ--OK9K95N&d;HP4Mh2QjK0yXNARK?{uMPQtPnv?U%CaS8Scvk89EQdp`+GVq2wXg?VK*pi2n&uk$6Q{9rh7i(mJ? z9EnOGX7e}~h%Z0DQ6>mwNBCS%^$Mw8bR~2av{NWz`ix1(< zeVgxfDks9`M0DO3ibyEUnD;`ix0pggkwNiDNO#m9L=ZwyLoiruz#2dY8{LWYk^?$DiK(Yavx7UV%a-kfc6mz}Rd6+!t z(oa!YY42*6S6-lX*88{g^R8Y&sWHgRR_bWYA zu6+-R8XszsKgkzpzbKuz;V4%w<~(C~CcqkL!k*-HWBWI%}FSU-+T)@zbMp17z4>4y#?G8wxULOSO79V+MFWc23T4z;A0F z6hzk4)Wqju4Ry|A_DLVa)5r`&9Mqq&T#&vzZ>M$P{hp%uE(+4WGoQzl5n3CtZG zQP$g>WOIH*P@ALt*LV(?8l6uzzG4NwtKdFCnhuVj>SmeTAq&oUkcbA6U}IzZ?u5b% zjoH1lI;}JW!f%N@14tK9%zoCHFen!b8iOqd6(28zvSv3W20gB~b!1C&B=R8IHL8u{6;D1q}8Gn`(rB?rs+M>J$eOph!8f1ZVe#<4ySkf)30QmQXPn2ku#c5V_2}O#2XUk$Sca&= z6kMFZs6{CKj8S22sBf2Q7Ni6_HHwwu!6GCo;7}sSOBgW5Dk{vY*YEMj(}@p~Z7DE# z&cjSur-f-17ssDqBF)PLyy#h9mZ#NfrLN#7&K0#pF%x9VS^mKMnu&y|$5 z45JaEF8YLI9{a2R;fkK(ILMBe$C7dQec~nb0to&L`W^#TEYH1+tOEa|a{yI@Y!X@j zz(C33#0;}*iU9t(cbGCAL(gRiJf-o{S1%6>{DaO^ybWmX3=UzfpPX06BC@-(C`Kp7 zkN%`Wz8KrDe|Q^!u#e!oj%zi|8SYH0Mvo)q4WI2m`Wm$1g991>z{t!Ti~T$SC_0&o z7VY&IEs2-wW+WI8DIe+xq2S`dNKs5`XV*P@b-QmCpXLdNA@h$-5 z-R#SL9Lv%pQN&x+6PQ+osI$|yt<7f1{hF~-ydKbS79xsZ%foq&H=+*X1b_qc(^e+} z0s^suqaYYw;P5ut%;+=xWi@7)@py1ReuYOT+4zsU&-eIETaNReM?#}Qd3Uy0GU)cV z1NVRLRJC?evD*WQ;!4Yz=dC0dLf`K>e7UvFc-`1)!rBVXXvVw^!57@WQx>75qAh!( z2C<*Hg##CI_TJ3~tCl9A{*|*e10MA>M(b$_1HMM90+xME+g3Qy?d}RwQAOEoxnQ#` z{lE(n?9_hf)h-&epK)&a5~{-6)*2Gn1{xiFY1_RF@*`2eHx-W%Q-F!2#0f5-Vi=1E z!#==)sQ;a*dv+jl^}-&VPVf@}MH|*s&Y;i@jT#E3H9;k}ihfRO$DmHxkoy27e$H@f z)5HiTq@=H$fr4Q0tE{=dNaPZ%?`)5;gASVc_R=CjAD4Q3mjb;Zr)nkw!gv<}iqrefQ5^)zdI0z(;d6zk>w6c#!^gh{q?F+v?zCM;1p&@j zqYN`I6P#WZlG6l(!amyxAI~c91Rrl7SE7422e?^b^g_(%us_Q6;*<^huj+@2v@R`b zh?z_1rEu=NA^*CZA4^s`+;h$?y!~w!$7m_hnu!UkXT-|qk}j~GT@zzV>@K>H zGDEQ}Qf)Y0X~`#z6aLOM_}#B9ch7K;9_LD0Pyweet(|1o-ldGLPqxR zq$k!*Hh{Owp=|r>G@Z>$;Nf&evBOiZF1~+^R?{o6=id;o99C+m(Gcm&OtzM5uwt^hvf_U_*;ju!vUEXqlu)0PqA(&OQ%D{pOJ3PlZ{|S z%A2*Q-bhB$2cS^Ss|k?*cw`}bg3-k^za5!s|9F21)X8Fx8XlJJ2DoLw&@XT!^q9k* zuY9D_o7AVi^D&nczU#p<%Q8DGK{Gsqam7BcD4oTiLEJGn_;ii{vLCT}yFe8>>r zc>9^@yIon7j88+>1zXHkU;0?hr4K;w?vM;p198MyuXh!q!#`MZ**Q4eu@9LhI9wu$ z(iKGvAI|w^r&C+vi@ZcX>!iI6h_yA^WvG{sMYn$>lKP$wHf0&xN{+?zL@cpAe@jbaqwTCeJ5e=b7$=c18tlYo$|ESG4LC2_^&87y^V+gPKV6SaKN} zFAJ(i$_`ZnfwDzX6CR9(XhlG_bx2#tz5Cen4>X8SN~^jY5|8(Nu5}-d4#w{^w+`2E zk)*t+sHnT>K_8FT_jQ3&@PXwxfHpsoTr`myNCz84PokC=h$)HNtUz2l$0JJk0b1b- z3mMD;hneKhDR(gX2;6U0^@z^Q+;$%wsVe}R6wFeZk$*AaKCRoPTtBTopb-E-BAcr* z>LdsV;I0r&^C%Sx^0XkX0P8B#kL%;r2JAkh2=boX3jpt`L8IJ-7c&cV)~17Ca`Ts; z^2i|;K-h_B;BEy$6*@(t#Ki2F>cKb@eJ1q%5yuaV}?Eh?LtjaG2{KJ3`ozV%__q zYYo{#tnFRBCH%B=_L9E}?EBHBf9G=mC(Uf;kY4Q+&U2FZ5p;o?R3&}$3?m0C% zKJNc^;l#SrG%#PKP&XPE_8WiGu}kIBaK)`i6KQ0vZT`p|@khqg)K5@h1=obm+8z&c z+*#tf%m0*1pGB|NjaNnp!vC}9{I@C?xb#Hc9?eK9#46CXE`tGC4_7WKFqcqFa71Jd zZsM+mO5Zrth1e*zA&g9I;$DrEX}3S@G}(C|0>>xWzyvx!WWpgAH7f7Jn+ne4l-+qBAn zRffil|Lr5mVTw=^KHXtBgL|v3mVEG1oetZ}8F?yf>)Xy&vaq~)rsyj5qQho$Ff_eD}`LM}$rkP7f)xHv(#C{6EV00XJYH@x7NS7w(&`%L+E8 zI<`XFEEH5%8kb^gS6f#5Hs@1XZkcFSo|iw@MG0gYo3VYUM3vg)2yD>8Ud z6D6(rywM)bVd-zBo1Y7E$l%ammgFmZ>=~4PMjKsdP=uC((Wi>%V*XO1v#xThtjadOEq>ESKh0-@e_ig=P$tnFK%XKVQVuLO$z+%oQK3# zrro1~5K7C!!4Uy`+dKFE_xB&rkpT8X-SOz?XdXa9;P*Je%_1ORu6tQbmR?GmL@Cj= z*{bMC2`0|?u%P*K)99O*s8|~#Nze_L_GfZ)3-j;C_nT+i&;p{C)B-!RYznm#$;|cs z@5CSDL14ikXisyeolAHDdNtZtEQ6#iu?)UNWZ+#tdUGx!HNNabMA22VAh{JX#0%5X z(;EVSgQDNa7`ubXunEJaQ!v8Gu*fT0PJm;3h*jm+*V+USmv%!DcQu|zFNQB<5v@@bQLi($azGPx0PJ^4 z*DJVwi0iHPT~xj6-&6kT@gRvIAt605bWC=;GB!K4P9+)~nFGx0Ix|u8U4Y6)cfdx;fdBAe$Di+|;hLSC+{qIj8|G4?G znI}bps35wd6|xx7`k+d7Z7k*5^GZlO#B@ZSvZC=>a6Fv?R7?6P=&7eo@DY#Y)}{O- zf()$bjR>8ZY2umlM8DM5zk&EXVwm>^F7{mp5q&{5c$*H>Xb9kt0Fv_k`4y+fPVyu# zob_lx_+Y$IjDw1vEqt7+I7x%NxoBrbHyM^s3D?Mni~@ zO1gaMu=Y+8RoEAbh7 zvyKoM)rlKspYd`kR%W-$wNSqMZSa0P)e>|VKny=vkz6+0An_?CP@NzTrxx8O6ShXH z0YWCpBi|qw^dXW0UStJ5%XPQSpXP{emz%+DTb_jHZkVF#XyL5sMn33ivv>E zEs*36%RMzb&EA-P|F%5G6=TC>`4To-$LKk;rZ9-=l2zAP(R__0idb64j;rbjVo{M6|$z;09E?5EKw}D0c~k5t0^=p{4rpT~x?4VRZ0mBrOD4psv`5^HcHV znVVUA@l4Fh)mO1#OzA7NIMw@aMG18dTs$JcB=9gH3=)_E>c9Krg`G|jks8>UjGW*F zFEZtAw{T4K6&KRfe<;;~A%q7Yz5$x72w;Bqh_VRyPUkozsul-;!Q5U|9~;VHQBN2Q z?DZc^C8L8;*_X@rL*}cAK`AnJjQi0dqK0a+S`8IOydaupQS#OnJ0vraz}nuV@h6>% z3$*A#wEEUwS=v6V1*hi7F!vs3?7UA`1#<)rB7?Pye`yBKg=#p~+!WV)dq=whb)H15 z_}Fpo>g0m>Br34aI3`kA1-6T{DJ^WhTzu=VSxg$Fm^vjb`iKzU*E@6TK?DJ?IDug~2@c28GcDDEE_4D0@! zpLO)Yw=FbLzUw>+n0ZDnq4s(Q(xCm17wM3@H`3nkCTpejyRH(|n|2-{)71}B&0*yB zIP=x~6AeQ|;W>Op zy8^0xbTFc~Lq>P!4QO}RwBIliHP5A_rs6VH92vxdIRT=~S zmUf3&b?}VjGi>n+#Gp~N1#z?l_B`;E@q#9zOlLCgj_Kc%m#-^fT4+Hi4%Kk&hZZ)nDsQ!P@J9 zQ+yB6@BzZW^T7P)>pwmKhoq)9U%qIwqqlQ=%nk<;*xxTg^u@($HSJW&_m^W#IH@08 zuvqZJ^7|9>)j+g=_yE@E{Nx2Aq*bu8_KXubS+;kvZO%HcuQqz4d?I@&gy!UYOtXdn zoyWmHGyHF$-?tLr`jv1p(>gzD*6cD5y6)9;@9C-fIf9+~lwGXYo_GE$Y9B+FfyaV_d{EH3$@H%1rgf55OkN+I|=l#}mdPav0`Yi#l zUSN<*Fy~Dw-giW44o8YnK?^FN8F%3`1TMt@ha2yrBAX$ z5;?4l?R}|QZZs5W(fI|4Ov8m9f`yI>E?&RPApaQZxYiURJk;19(`^73jD(SVe|dj- zM0_|%q`<=``L}Pr_dfrkD`S1^pcu6b^MaxH=LTJkVWc-jIpmWl*6#=kJE@fxZ)%hc zU$7WfGtVetC@c3bA8#N4R~6t)nbDU>~jSH zJEV@v&JVT`SW==9pknr2Z#y*os}2mMoi`(r4(`Yr>SqwBU@=dI+h6Ce zt=X^CRBAb@(2{oV$P&SqW+ZoBHQgWMy{}X(s2`UTfx>Z6B1R9I3@a@ya|GqU);rD* z$1f-wGVL5r8vS1ju+t?z*z)O_^i;X_0?c{wxW-@vT1tu*aS*LaGA#cuktMT2;k*pE zND~vfWbpy%@Qw)BG@cFmNUbX*UWKb+*+Ta~#>BGY(>M{*zL7B;`Y=Z_iYb(+a?6xl zDLZQtCnO?rJ&4*oed7{&(5m5 zCZbv}BH}l`TDziXZo-5{n^APFwH4dNC~etc1ATp9Oa?zAFsX;n&-hwy8Q1EkEFgh2 zu`RFzjm4g>nTd+h8to<+KmslL0nfPQs1Z}ZXy&lgbSuIHo7H0C)2b_OI9*EtFS)o& z`J9#2$?a$cePfz?wR47_k8r7`d>BiV zYN1WhL;_f1&W!EO+WQ+IuvnF@P?vcqZ?}?mHcpdB1M9-?&hS z+UFs+g2;rE5>{3|@&PEMP)zOYP-JB;afMyJVqh2M>udFT2T#WF#n1w(o;Dtf$xLOd2h+keqiMqRYFH3Tu9n!>J7mq5f@sTuymFd2a_-3Rk@Uo36Qo1DY6pm`Ve?D=ig1yO!^jVy1Gm za-w>nYD%KD+;fAxHZw0FT;>lOxdv5@207jeiFFvcIjnOx#OM1HSoEcRoo~>s^4TQ&D(4~Fh{Vtm|>3|LvBZf^hO}n`Q*^*4?0JG6x z4MsG~PQMZ6?qde~wBIV=cRXhfT+g8?(7FoZDls}WK`b%#0D3w!R06P(0^`-WnU~F& zg;z(8nS-TafPCQi+~W(hO8~4%Gg8nZ;(051lh3S8;)YL!VJ4|z6BB*5dYg8qq30Td zUYmwb-OHHxqTShv;W&_Q+cRn2H8AInzpP#+qKI(riT)=w?CDeI+>GoRPVJ|{K|^%B ziLQr|(Q0U>b6r_7UXWIo8#0OanF{~==H<@m`{))uh z-vlYIJwYe1C;^k`u1(3L;siFaG}rZ)HyxG}g5O({a!t-F;sHn=ooB?<%~&2@RN(WI zjX@IKPC(8#KrRvt5qjGf>Idd5mkRxF71PLVZpoA)Y370vy#JECyD1A+J1{GMPh=Aw z*s1?$nWf)ZC~=_sm{3172|cqjFai;OEnx8M=J+v`rIC)3d=lKHR{>FzGfMKbFGu|= z=>w49=16l4zs?5u0nbc42oPy{|GN;WnkPT0PT~3YkM-rj-Y@1?2^EwG+;`4TYdI*- z&DVSn&8Xj6biNrG4DaiG}(-Z+3ITB1hh14TxF*LUuHZ@ih=lFs8yAkPLB zLxBLds&)7^jXNm$<{bArphbXT2E`kvImN0)ceDmxCU>GIgUG8rW1w{5^#DzuE~qsJYpJqa5`E7GyFenZ$NLOVkpGQ*sm3tgN$OA0ZG(`a(yNAQR-EoBgj9#V zcU4_t0g%Eo1gWJbdo|t#g4@k2nU#HeU+6wgF46R)e&Czv+Mv3xuJ--PSSi6LO*e)k z8346b4}~)MX&Ay(aD{!|Kj;>9Qhr4IcF1D`)1}Lr;+rW$-_#z7DUv9ettRkWmE+Zw zlj8>#Td$ilJ|5G&mmO`5Ay$+s(-8yGO$O50S_|Yy1kJ_In`!W|qkDF{^Z^g8%k5V|$(WIY z$1X=xt%b>K@iHX zDV{p^g#kna+(d-j-v?lYuE1lKPL!X(*rpwyCh>tcN+aGBzcLlgZwE7|gRGVX1krOz zUafIPGjUd)0@3~_Z9ts&b1%e-cz;%m5(ey;&F~kP$kRtb$q~Q~!5YW{S3z%FKY(DN zM_HrkEFvS{l)($S8boVJL|@?0B+W;x>2tVY^}$zbKyvpXa-=v@cuH0q!GkbiRMy|HsWc6JJ70Jw?jY3Oz+6lF8qz#0}jM1x_g7R?NdddLD_13|fke*XQQ78FHt*tlpPS zyc}6duZUzhS3@=uP_+Zn0tRO0JwSEXdU|^2l^G=qUb1OtYHl9tLvOIrZlVkhw@R%EPqF zp5&F(acWTX9}t1*4$K|+bVsgYF#%dSE&@#oq$+*tLX3lN0hW4gg%fN&o zqK)7eMyNj^u`~hC^r8)g%pABlm-BSN>aQ#r~KHmcm1eysDbt)lj&E&&66nQJEv)#iFR%rKnVgfs<&OSr7FXVcKXE&?g|}gP~v5x zT(x)=8ShU7H2y*%SkjG1V1qBA0K0no1$hfN-`TEe{^oJrd7ZQ+Jp_|^%=unPcKN&m z2DL`d=+w+=&8l=mtq&SG`W;0`Zn%6`Vu{RIjJ8ZF9rNV$=Qd{r@{j|DGHc1D=)q@N z3!jub$lnCu*qe!g1w`jq(1m`aujNXnnusWciUGV##vIdXXt}~W*38aFaT4$T?1CI~ zQQmc3C|z!sBzTs{uuEvpWnxaA8 zIx$kxEYm92(Eq-b8x5A*Gq*o>@GBV^cf>Al126-N00jimGUQDWtB@vq(s`{+ie;VE zVqzn#f9f6E+=cjFY(!MhlJpqM_7x(3MdbEnkM>i!nT(BF6!@%|&Se7;WorFlnDgJY zu@H=iy13%B6yI5*Jli2NGc!eVaRDbF6d-M3FzK8>PT1-O{%+m!hlGD=X{nm1e)YMI zI;3%H6<{f?bbE9EGiZa|H{CzFdv5pf{H@3~Ny9p!`e*I?^ur9jeu|k)rTO<9%Bm=O zjMiBSFS+X`zPEn;de9@B52_iDX@Km8QyTmZxAZC-lS^r|DnYZQFa*Rgob)n zS65p}38?Ozy1`S=p5D!Vt2O>!6G<7Fl<6AM9i#8~KgY1+6Z z@5r(|7zelc{$6a8N)~zNZ#Az{rZ`QCTk$x%nYBDumgoSkBJ5eUK19ERl^isQW{H0n z8k|5R_m)myqR*T6i#8zT;t^=&4uFyFMw9XyX!He76(c-11%JxZpTw>F^% z%|2IE*?v6CPp_k&{ioq~<>yK`O7*m~`UVCD0;HpkgOE&KG;?BsWdc#hE?g;f8OI#A zWYa3a&NGO&puQ>O->$`dHOHK`_1Ll~EgxO@UOC0)O(btah-J23^q*-9(2lzlHGs?Q!cpf!W! zae82>p}f79o5upc$R4kE%hw-USKvB_NK0cXT0YgSB(grI29k2Lbaf?)8lv2~iaPFY zy`e;`sCl4HCUW9hv07#3f$oiL0-^8~M=~nS7RcnI2ETnfvX;uVJ~rkoj_!j=>OmuF z+jOJvc{vao7P#LC2FCpgL&)4r1lJ8i=r&G|PfX0)L$P-VHf(>7t$muLWlJ#d|1K^ZFx&}rV#>Iu_^=5NG>{nrPMVn zsc?;fRNcG?)`-XH2CvVh_x3O6nO6uuG*!UzIei91(<5Umc^3LX1+dg%$XBNAAZISjv-kp6oL=iYi<`2VVu6bxZS8QWtuF0|8Pun33!uAh?dsl* zpJK<9PR6Rs<&USC;#^yxSQclwO(x13f!t`dd_hP=y%8|v@dLk!MM>At+Mf$gASuQb zmd;Cg<_U&qQk_DI`3x14oJybno>K}w{FR$~6K%ZM*GLU|p5hHV@OWU4z<}2kTt>DT zpAC$1r*QQ+lU3-qvDG*ke!a68cF|XOi%zg!^&}TaVi1w3sVUqb8c-z<9M6}XQ(fG7 zEpd#LH~ijqZ}|B$h*Abv&;z>F@1S9Z%D3|w7*k+%d_E-5`^*P$|6rGvG=87noq>`D zX=(~%L=+1~_ETICPvH|lX0YFuz(ex6j~*v4p5@?;VFSvA{2h>{VXB>BzX-I^FU&{$ zq^TAZ&ZLA|k)!c6`?6Y97=Q&~tku7=0w?IO4to_k<4=<3cgE_o)2hoVz{%Msb?Mgi zQNiB;8RL2HFCZT8f7LJ`sxQ~~H5laQH(kKvELOExnvZ2 zBgP744mtxJo#B&{O5f=govEHJK3+l*w0yvuFcNpp;{_t-@i}5i;u$V^l*2+IBJ)VJ zrIc0q^iKg-RT0ceDf2Tc2BQk0RN^q?(ToajV~F0&S(Maxpd~0*1#*S`$Xe*i`flKe zmu?D&+=hhwj=e_0?hBPy9`wJ9&HwbfhJJhTR~3La=*`!gm5a*;k&?nwfEy5~|5M84 z50o@r&0N!J>!WOlzS?-IW zowfJmwH!@!1pOi!_>Q|j0C8Q-d&L)g*+n(=@_NdQA-q`b!ss1b38Z(RoNn%iGw+aq z1rY)24Z63dx;)7OEPisvU|DSFl!Cw7)()>E1pgw5$D(c7${b1(4m&uVj&3{K57Kl$ zi1ns7ON^uQM7ftm^ESJNZwJ&LBCDh7DkqzzbGKFd%x3@np*+xI9ss_ho+4M5EttPB znx90n>%RUhFRy4bh==N#xfeTM=6E=%U1)Js8^FqLQVhl=jX_7c!jcei+ay!eMJko1 zxcg*knom-;Jax0-MBhOcLXR7iz31XIfc^EAOlUzP7N8p!z=L6f_2AU(egwNsmMZW# z?DX|fH9Z|X^${9nczY^*75b^f4!%MeyGwk1b>Q~9?eGpchhfHffeu_T&#*6gWV^Xb zom?OyABMR+-{9KO>J)Cca*nPiRVYg|=?{;e9e53j_N~(l;Sn@zHPnm|jp#8~E7z^C2>GZtj6Iyj=x#RuJ z2o* zeVP?`IJ101i+_8gzTVw_MvEg7{N{Oc=xfuq4gfeHKHi=WN2tenizX0!8?9JY)YXWj zvan3_s+v-^d6BQCaxX&Zz@y7tw ze@^;DSejsu#edrGme#KhnEmkqz*qfUK`+jJ*dwnVTJ@tgOhw^IRQoOt$-tg0LQUlF z;pO*J|6kXpb@L~*6hqyr2&0@k3)-<6LlfBqQ_2c;zp|5#hat1c8QG+T`lv}gp+5Ye zCX59K=EPr5v1_vS*sf%0a03+alMCat&S#8Via}t#b4ufj2&sYh@Cm zD0>zx=WV@$#F+2^+TmR)U2{iNK-qyb)qX^w;956{9gmY)UnB0c^s4%)-QtD!H&UMc4n7U z*PjMIV)h8VIliII_gD2P7m&@@377m(gJ9yh5;>f^)_H$b`11?i<1z z1e9C=qyf0qfu%JEn$`MwYYQA_ALIVv5+D`^=E(;K*e+fASQ3GWiHU))r@+anD*M3* z=ic<7_&DGIUm*Y-gV@J3O^deMa`<{gT+X#aTdf!fvxF0ZF+HDsB%uSrJ;9M@pi95L z*(FItxQo$-#}&8{^h@5|tR8$=ODZuJs1ldYSA+R3+cEQe9*liX8l)UA!~IeDTJ78H zejK(eFD-q{wwDe4iF;oTm>pjp905#9;r8XRud|{1?Vs}H<7S}SYJT&>l#`pVYRmE( zQ8d+0p4#V?>e8#&-`BoFc44rOJ?cerjMu0$#Ye z9(!^gSN*Vc5xC1H8yP*cZ)%@$*cX z7wb$xY>&S(EHD+swM!bBAB2-LAqOyHt-zoG>F&5sQ$X%F{v@+r*p;t<#-WZ*EX9?t zIs|f(Ny+D?D#>9g{2)B_&w<0`fFVYEc67}ru7hTLvYxS*t?l`f-K3mLi?)JcRgGBO6`HB--@GN*SX1ORQ2?%$i99CpBGu@*B2~ z8_%PL(;;il)i%bz9AzeZxh~Jm)a()eJMtb%AHh&LA3MN6#40$AXodA_|1|O@Q3Bsy@uU3y^~VGVN#(9LfO{f3PElx|U>_?A%=m&RM9{asT(YFu|CK;?Q6 zdnG`X%xZc1qc%XZd+&q2ihLFfi{J8Q7Q6yq+eV$IeSQ^G%oD6her3((afE1U0{uR3 z9h;;r2wA+80{SL^X#^0yfFG+C;3w0n<%@LEilAC@ANby1`czwZYlMB(sKB>43{0X4 z{V&3j_IWf_yh)VMrlHuXh42tfu~0Q+lbduo_y5kjQ2hT=8~y^&h%q)TQ8ZC77*{Pg z+%eGh+An%JnU-I?x$ThZAn;7BI0zo1h2EXBd0i25Zxbwe_Y6pZh*O}FbF5QROssCM z`}|cjY05mCFFCF8=012QbBq?cEL)W(%%Upt!<(50XX=1z4z-=isL9l)A|*xaSRK!;7l?*hlp&R&dr{+y5-euK-j zvvR#}1~+hPCpAkr)BjC*mrFY(g{;IqWjt;?UnMIHMdNP_BC-#`0t@LLDJreL&T}3HDN11X}@9BiaeL*0$qYuB77(_AV^wZ0Y zg#Mhw^-5IKi@bfc&bcC)<57iO@{o77ls_o=$nBf3e;f~AEfFvD|cq(WE@_@;oj zQwmrl0|%?)ZPCb1snkGEtO2_%Q>2+ zv+mU5_@y4tIP~xKEU^RYZNIBm(pkDd)+9GYHHe#E71$?ZcXl~H)qHf8S?n|=OON)} ztiqG-S`yU|Bu_gT}h6X)^TEmS5^C zy@*Co3+VhDxbZFLm#SO;wdLy#IP(mo8QbtQ=&d-jJYE-BW8%R+ikzu9GB_$InljfPn7 zHjofp1{g_eJ?x)+lQPWZc{G|jT4=dunt;R@b93mbD&*=KPIL)h+n;|GB`YshjbaLb zCh7wd(&9`F)Q~YB6oj3?Q^21`VuBMwPPa$^&^Q2LZH2W8N6+w=Ez(Nmv^{ZR0ol$x zv^e#;`oB}62`HXNKQJm{9HqBMa&!3V-}}JjW8!rce1rMzIS7FEox#9kSK{T&Qs~!M z^2l$iYAbYNG6hpPs?&Q4pfb7j`iNEH$g;I+(>=O-60chfjn-}f7WB6ZvneoM@3mnI zTMx>A%j&H$0H(#!y`0kH+*JhX`N}Go!Ke>_OWkqKd*&Cs@0c-;)_6t=0uwiNAOzx7bvR@<=v?HO+F&**7etxk;`pJy12Q*fKMQ|6fZ#{2q91F3Bv@*(Q zwQyPj+Bg`an0w(M>}NUE0Pqfwh)r`1xCQ_F%Zf=S#zTqo4B=w#7`#`>UCb zM1-?K%zz3)wg40(rS@6_Ur*28?s@Y~fjT8&2 zAlB+Twrt%vhu5@B=*NsaOHdl{NLfQLXZOHi=?GKJ^mPZgARwu>DI0aD=u_O}Vj>Cv zh4NmhJ_XzzP5Xi#E@c0l`b`$s_W^3bYj^-93H~9k)zHv@nT9eIZd(slooEdxR~IE7 zl}sq5<&Qt|iH`mO1R%5U@kNh~(E=;a4=u<@8l!GC;@Wyn;@$KxF!dN79%di`!lg_c zt>GsoC~Zt1R;sEL02!pX3hAq#IGl%qZ#0Ff`>jA^vVHdOz@B+MPZ%}Ti}2+gC$_8? zma24QGLoMUZ6Y?bnXEq74~QQ)xDAcXAvIatx?lbPUw_&UO^4k9qW_eZK)%?kpHlSJ z?4Kcro+292>Qy*9aN%h$R@r(-lc)P>|=B#DCe(`k(#UD%V=SvjcEH6`!a1yx}-vKA7RB&%d)wth(*qfqlYc zgbyB)M`&izoxx~b1fk@9@%H6DAE3d{7I4PVbC6~+^8(EvdgZVn(WX&Ttp`=7G=aBB zfYCI6Wy0m~W#adn0-T{%tvWjhfKwR_;5mfpVW%;20QZ`vp)dBP-LlR8AJ4bAY-E4> z$nDumC<=B6C4`|(K>+cH4e(uHFq4xr-)mU}TEI!$U)}icUv4r{z6MG946FR9e;dZp zpMv7uw~kWI#e@aouGw4=A}h!lA2;aSJ;uDsOi@&KqrRnIq$SoA-paoE z-8{-ym6p)Hw$-_ZiC!Z5-^Ra3pl!GDkSZLxF@c-dBVa>j*I-d(e zEu2u{Br<9OFbf37NPeZ%lGm{J+kx`n{%_qs5}Gv|3K4#~044z7>y0oZ2naEb07l8u zw2r6!=REDEkXw3MV!5~Ift9*g2y~-h3YSekkfCarqlg?gBofPZVr-QQQ1eg`GK;63 z=@3F!OGpTE(7)jkXXneuY5;#D$K&{xDqGiP{gZ-+;LA8oP(4I{fL|uXl=a4?T;XS~ zHCjJ68)Vb3k-k|r1n1pvqZ~8N&qxY?4FT5!AmH+S&dpLxVhuH@3rECd0>)VYZKH7B z+SJ8`C{-5v&I=oWi;2Rmr*aZ}IF5_}<=6*?7-;yozORL3WZ(n%4dj>U%iC}1&Ro2_ z@I-xJ5)&@7@^E~Kk%iLk=Dq=mp;xH>4-_x2LO!TD8n_aP6p^2>dRpg~el>DH8|IQ9 z4;`&JHlqq%sUVBFJfT}K>-Ck!W;s~DVE}L5)nS%pLt|r2IkN)}m~wv&^xes6-n2EfHTS1Yn)s7#4~ zkj2-xtIWQ|edg%c(>kGu5fX2#c)_RimX&UTv?1T6Wz`KW`(~lD(IZ8yrD#GhhqIRD z55si=K_#7wXo>%!tP&qTDfa7=cBXZye8yF5odB$YUDPL7wgFQaT0eSTi2#wv{_FuP zu`;oM%hP*9RG2WkE>q}Cpumsi-tsW*!~QLAyETP+ZP%lfRI22u%3tvpLQnROHUJ8V zJpFez9Lv2KA?pieooQt94QsJJ2y-Of)XfdWZ>PwJ%(aAru>2D*bvP?Q3zp7^w}aV% zhBc0U^<8p5Oeof5K?qLLwJ)llw85=>KmL0LBRj+8Pw~*XgTo+QvWRP0RDRP{xqukT zxPoS?v%LdobsJ9L0+>axgNjp2iLP~hPq*>xp5Wt`b*{42Bv|=s#16h^^UOmlGv|IW z_i37$tG^^17)Midl{I+Zv?~};+KF7s?0Bc=*zeqNGmAN*&Y_ZrP+|)y`XLV|#t#oP z8-lWRwGEjl`(&U7t>D9sKd4S<|Lmq0R!}C(qa0#ArXvOi1}Jn~JIxNf;92 z_E>!}DGiH_Z8kn3s2#xE=@0~J=WO91m}4 z0YV0_-9AAEXnjC9Ai2yZWP*ur_Zz^7qjgENt2@lCE7rmp8Q6p!xpYPp_I#!1xYXs% zq0R2@Mq~-mm{)THDa}-XosnprDmqw5_{la96hU5|#`WO!!OlJ-Qw#RH{R~GT9>7$3 zL4UhK6^aI|Qd$xt#+jR5p#dp>Gh+!)6(}cd)7d$RxHU92uW{e+^GyBxwp8g6gY#tB zZoBkd*7U`Fllnt5u4Ldp$L!!@ONk<|d=E2A!A==;^VoKdV)}M=A10bzx|7=n2?*Z+ zhcB9L+c#(q$qz;7_R~_^)lJ?zkq8>n>}TB?oGuGYA+VSQsa%dC@@bwg=bvrv2x^5~ z(6ZX>N(BT15_O1y2&I|#zn+M1fzFP4Us;&iH)Ymkk;eV}WXfjw#Fcb%z>2CwTu{Ep ze5wGMWgia?Gg9|L*`!=3? z=jVEZN)ZKs{k{=kyap&KgJ)+%z%e&##Q{trzAL*0-`jg}!7M%=%{;8&X%JL-oDVrV z$Y8YfT&jUH2=EzjOKMDFd5iWf>%8}nlEFdVb`tAlcLkLEl0fV!>UN8xIVoDSF?Dst zwzW0${0Y1Tsj2211QS+Vx?fg7nQ7^30`-Y~-D}?V7o5k}-kJDltA&9Ea$WK#5Ybyw zf>&F34m%D(G|?z4#r7KDfZ`n;NWXof1yq=7A4s}RoXu_nRO`&1bK-7|{b8?psC$Nv z_uNw2o|~M@omKxw+%L=oSUDy5w8fI>Ufq7Q*+r(c%mS+8raD0Xg=}~GEfAT;wyxIs z?{l6S76*+6`EqrlMO*0i^|t+JLmwjUEth0-_&=U;A3=)$Sw2ETp+k(V^1?5lkM6vb z^yee}y=-iHaHUYiy4=~IIl73yZT-X#My%#%RLQk?fY+;!TSo)CZlSh+(S3 zAvk%n(4n*XNuFf6w?@lWFsB9TWB8Td3W9YK<-P>r|r%7kXQIU z0f%{mt?9K;XI>;5hqnHy>>5NP$`XOG$wi}$L?biI1wYJoVs`t|SQo_T0{)6>>pNv` zIA?!x$G11o5iR)c7kf&GiJ=O!lO%7@$S;)ylD-+h@ygYBq!=YFu-1R;MPFk>_M;wS z{d!mL+bJrecgeyFD%TJt@^=O=1K}{-jkni341-@B%Rn?i2e2wz-#IV%2A(HF-FB@p zwK)9wmZ}P9rPDJqM1aU-0Om{dtXK_M%}}B_cF|JSwLJQnqw~Rhk42_-`x1D3kS8W4 zfaH;+C1|bIH;7U&wt295<8DIBL90z>CdQ)eXtK~*1WO+yj!N}0>ic5KuN<`F&nIfQ znUwHrHKinZ$unME-vhi9s%yFGJJ*D(7F)e8EQn3y6KkO~Q~UUf<}@y{JD@c(TYg`` zt!z%KMwsEylR>pj$51_oYcswT(xAV{9zY%ft}}nqp1-MeI~1gkqu6`=7x<3-zP({- z5_fyx1)>({CsJ+hfb@SfM_47El|ky2*_NHLgDgN>2jMehIM_kijK=&tZg&17#U z*&hJx1V?@{7+6(R)!F9s{H52PeXA}rl<`9`R4@inAjr7nw{VT>FF;rsQI}4stPD4R zkZEh{aekoL{DUVz9+@mx!TcB2SG6>oV&+Pa%t<-)GEP2ByD_C)DzxUxyFHU-?(y_^ zqGoenuBz)47Ue}rLyqnRoUE{Io-IfD0t0Mm#|Gs(jRT-(kBN`hCHB|!Fzt41oCx&g zYl?O!AX~a2cR=q_5vMtj#WV6Uf$CNywFKe(wrXu~ZH&_=l&Y=|p?4;H!nlzGj+0nt z>7=2!<&K1eT-1xu1id5+?_ALX+7uWmT1m+-@>P`9jmX&WhZn2~t8u%-ry8%r#1wF^ z{Y854{Mp^@A%-OW^96sb-a2mkkw?cI&zeLMz+>&gruM-<)6H@)>JV1Xnx;6>mzfW zo#s)`<#g81jjDS6+vtqUyNH1T1*>*|xz`g0)A`m07vtZvOZM^C^6`rPy=UCs_UWBV zwRiZ5O0!_Y39wUhKJ1-A@%}ISc=-6*?i+8XetK1ogV;E1hPF|9O>9SQT@TT{5B`pS zhh!X>5-d{M_bEjRsgj#gh-j9@HZ3!9ZLAb~X?Y63j@3k@S))PvHG&xd`ybs_y00AcJqSCUFKMcI!m4se7EG#VnmjfeSivcN+)arEtJenAn z{UboAH*lfs(4xXiFJ8EwM|b-^b9smgn?uv3qJ_s3^$)G^Oy_zds(O`&V?!CIx(Rp& z^2A1tR5)SD2&#uBO^}|WM~h@k{rowbgbqfniQtJvE@~D?1{oeDvL1`T*DB9OwrnI& zDz!Yz=ZzBg$#N+!hyYBTkZ*42g2+CbWFonM{BBz zvuQWH<5Q=cO}e$s?$^rb?@>Q!qRz}+q&$X2TWJu!Wo7j3=e1*7XYOQxwucCt=sm7# zU)RnouGl=2_TBA!Pk?H3VKK*KQ?Jl>gOOrnDn$vCTlN*oh|{5+r86bcSzLMsbJ}E53Jm3-7 z?%&F&pohpNlyY`a9g7R4w`ebl#H#_ApE_Zg#bkBGA2v} ztO63mSsh(54J@k`;4{L9ZW4+!1j1q9Z0AgJEro+rZ$y}95WkXLK{V?SS958i+pbZl z>?1@6Xwogu#}5?NDyWwJ_H&dNndzu^4}a7BLb1apg9{ydI}wCH6ZN-Nw;FXq1q;cM zNI!6u#u3V*%uoy8(Ah8^P^(ktK41tw{f;kGt@wFfyP4X`30gTHkRy_=AoOP(j@?Ct z6y*@QL1g|J@qrlVp(OTd@{92H{iAZGl~ZQ+&Y#k*0JIKWpZwf)&iiE|q)toj>C0F+ zd3@-iF+x$d{P^NFyy(sFKFO&8JuXeu)rRxT?!)yyVD*?JfVu3-{?m0H zfZG6UMCK^gXiz}L&j|3L0UwrbZ?|*FY7_NtFktFDa_+trXiBYUKUYA%{pEfDr*FBn_*Hl_)1?FH*CpTBx@xJv+o)*FEhIUyh3 zaH-&0&T3G(N=BYk1%xiQ;!ZMYCpakWixHBR&A$fMPC*BB8Iay?=Q*LnOwIH4+M@&| zZ$(dHkgj54B4{al>_xtVu8+u(@G~V(K=mj%MbsZCOO%uG{s10YhXQodQ!^`9oXL?y zU)`$)zPgd+_iKqi+Clu03BLqR9$Z<$-BGR1RRZ;BCu@eaPX4S2Vy}R8<$A594oD-k zZF$l6JT2BifPIYqkjP%;SksNizXmFnA(r6HaY*%U1L7nC2Smyf!vL@DIAGWiVw{g0 z$kt8$gG*Qq9DP0S{_g=a-`n(!s%pC1W?*X$l{xQIrwDj~UvIpmDK;>n1yD|j6|^3H z(mQ&wm6|cB!*Wk?pVzJ=ZGQD~$N)Ml^rcFxyH2ax)&xr5?)CT@J$fnz>*!W~O$~<; zg`mS5ekGfI;tR6d-Rb}+9%>;MIvgk;L-HByJ)Sv!Kiq|pJ9XiGp(r2yKb?u@T<-?8 zgjhg?N4yltBjtx15xC~oySVrTT%rSZdkGDg@u7NY$7_GJ8~f$nEkOgXQhanry5E1XIZ-3Fal%0dqIy&;EH%QHXE!!VKKQ z2oHV%g!Vtt2|rW!12%47I3@=@IpzB=Brdl(4G?VGIU88viB@2`tH!c|}%> zK+2$})s~HoVEl_`&(I1NN`N5qgF(&JK>ufd`{4}$oUYVO`AsRiQiak?UX<2k7zBS` z5%G?_dG#%O`q1IYQz9d9u9H~fI9lcpi#o?crDGS-uYK^S^WZU~W@tbk%`%1_ZM+w_ zB1;us$BWBy1%EYEz~lNaGwqB~QliCURAB$mPP=36+d7eA2o^H!71GVHwgwh*fLuy3 zZpP;D5&e%j!K>wOns`|_`?`46`bAz1222G4nPJ?zX9E2{263|jiO@M2RQ@afhCzF2 zWWU-@1vq^$Fff21NU-Y<6pxASpiJ;*!^66N4oOEW=Z9K^GL{SQJyvl%O0+XAPtzwu zoBXrXu&9%g2l=T_82CiIrthN8E7T|<;%0Z}$Gn4UHxD9Lf>afiRe2=Wz)4(=6f}U5 z@$m8*)%TetgX$GxM_{@StycR$6UawOSE{Jmdg|D ziLtM!f2jRZ8B^YOk!EI<{O=n0ceWa(=WwGK!pA@ zG?dErQoTca+a9;GNG{ti=QO0kXKMe2(B_Av_ZP>z*&`PJ^UGc6M-DgyJhO3?_exyi zM4{o+i^GLB*trc#ZdBpHKRAEX*{LT>B8DhCt?6_9%aKT-UP7hQC_!*0WQfk!-1P!C z5+TJD#!%Yh#MKOVvHel0JKaDqFU>2NL$etCz` z2I{VPgjipiCEi$b+lp}gUOAB~Zezh(_^u;@!x?ne50x8XT6NRqcJ~>R+H7#2XYm3J>6%>Zmb9FCqTXqbYP9;uGEj(O{YFZoZ z6x71!)m*}a(!8A0eD2O%uQNR<{Z2rJJX>j1vYEd0*gSB* zD!a@c7Szevc7I@Z8}Pgtz{u*K#W2HPPOlW-52B2r*Dpm?lSC&FGAZ?eaFkb$K^wTa z+u~&3>T?{N0Ly~uIOKw~)x(V7ykRC~wHRNqo_Ey#xG*5B0N~E@z`zyzmDBTlzwfxQ z6}5Thr)KwK>*vpO=)P9*yiZE@YF$sj{$$|{fS?s#*#CAdVF64XOxETD*5KTa=Ou2k zFoC|ru?~jVOYaz-Tmllrt36IUj@I=bqa>~bvS;(1|dyC9#xIDB7Vl& zya66N91#Vl3+DGlFI=_Q-0xrYPOt^x93*}~2n~cBdZXGY;*gUoPOFX~5=uR_VoW2W zL5nG6cOpT;B+)^#zF|i2y)qVQ)Ts~p#`zI(RSL}1sVE`wBk3Q`WQBNQANcq5#=8q) zDQx&o6T=5Mpr_FzkXR4>p%E@#20!}yRDm7t-KsuRvmAv^80+NHW^T;7Y|Yv5r*nAp z7~cKW{R*QT+uvIA=HT;mJ`*w9tPuE-ra#5V1|NYTCl?pu*k#QhS$SWNqkx93Q&D(CQr+L|&sE=atJcYH1 z{C-?97gp4cbPg_DQ&_a{(oA%}8-E^=AK}CbkDem+`q7;3D5~5pQpmGBI-qY?vP~q1+iy)8;>X12tgfZDIJTW>hmQpg$t^y-5-bY%PNN)L zBC%ivr^hSGduPen#w;8vtEt+7o8L-}5aY$Q>AyutgsBgX*vBWrbM*+5z0S*)+MH+pFIdg}H)yGS7 zs#72Z{M;E^Nl*AL+ZY{6fyz$%4d+q(s3-OadfliR+lod_!OE6qOMgMl0$6SG_H1@jfb4`myXw4#(Ys;jvrS0s3}>%O>9Y6;NG0;Vj2J zoOaNp=wq$;(@+51i{}x(^W%;eA4;Jc!O{!_`Dg^0s+z|7fqz5Gk6CY@3kwU2|9o9} z{_@{S_!i?DVCd|GI_*JC?U#S2VVl51AQ0Lpv)22+hkMry>H&~r&xYf=etRS*kvaWK@tHXx+(HEbJkUMF^_rs9!SQjYX1_^nNyI+p^ayU zq4+09v9Gc}W)x8e1!A)^y9*0>sOp(IiKDIAWQZB~b|}2Uh39fu>G1CHb6IBYF|9Gf zexuRQQdl!tpPpjG8cuzb*ZGT1B9r?LgkZ(Wl0R|qS^m$YVLC1~t>1wx8QJ7k-%wyu zq|i2Xn6c;5UAyDrGn560Qz#cQS*;#TR@ii4C`e%pF&JK&4yr=Z^o8YW#`_zg0 zIYFrR-|fGbwr&Di6+~MVmh-fVL~B{nM&SB%yGU;;kR%iXVPuT$s;7ATRH8!0ePEv* z6#=+J$(?^o?PixI4fhsI6oghLY8hSJHx-_D4z$e|^nSQs-QG=Qc)nOrQB?&r9Vh=o z=|)g{qb~jD_>ywqezH(=F5$6>%*+*NHaECzP1<Nj(2!2TIXF_6^QK`Eud>}1%BR(Vs@QnT)sQa>oI75C(!#z7>#c5 zw;?JZv;wkUq}c(F-{*h3VYI#6^E}^WKa;IKjCweEopToK(lJNkakiO~k62!o2Gm8- z!2S8U`n>hm1u@u_z4r+I-|w#&4o!E&-*KwmXK+N9IZq5LI4&=hk1c*w(@Znx*=(|G;kGphVv zpmhb~*+<+zRgK{-cE)N>;lg=C&YMeq&u4N65T_Vqn0JfPWgSFY%0S@@Q+In&1 zOGJ80zz7rJ zBCN`Xza=hQC;FJ!ciQJ?T zJF8hg4HJu7R8%^E^u> z?qrTzl=VlX=b|3)GzN!5Ky^a0eb-fZH4o(f-Sb#t@mdR*4pf5uR_DaudSvwc%??XK zu6TcSniE7PiFzA+m7#!~7@xOmWmW5TsbjwcY`hLlt4V}sAJ`>Xx{GK|ugpE!_>UHj zn|;z~*$Tyt;Mg+wJdl&n zBGnxQ^XuY5Oy`uTHW}8TSz3xgj3ehER>rw*AaQDVqnt{?>w!=AB|acQ?lB{4hk%U9 zE0fIy_SqZe48|+AU9hOlG33qnca#v1Tj~RP2kx9Az2UB$r zTdY=7|Kzh?@1_-|lf}VZy6NdySBRT_$JEkRzj#k+V_79P*woPSL7dfQ5F}tvQ81+b1v01xgQ%f~w-ynP>ZF!3xbEs+84E3GJSG5+6jWxYG1vMA)? zDIl}%Tou~J+IXrPbW;`92xQ^Tjvb#wp0|s~=ur{HwGKA?L-`fdzmTE1kySsyKew^$ zhwJ$x{gM(W7pTMjw(mY0st}@@Mm{R8dn8l!KCcT1PB~(KLeD(SNoXpE| zJB`K@Bl$n7y@bBp;JgI(U2v{28Gee5jREo_!q<+X=ZMgoks|XO>`?5nijb0gV;qN%l}T%noy@P z-+c^`1R?F;T!HsXA$pkb5b78HK;+R6Dm|1eVyNt#g3X0{oT{ z($iv#IBD4lu2IoD#uO@6YM0ektKJwbupIbf4Q9}x+K z#W~J?oeQlNcV{{N-k(Q=`l9^If$jz-yV{K>@}ff+!>kqST`oz@Y^-~6K>M?c#)&oI zJ*}c^fq()&N+PRA28s1I%}`C#DbJE(nG1CNsTqV4uhoKNU=+asJbnN!Gkkm7!fw~c zt%ioe`@>Y_fy>m}<1S**7Rx)H4%LUS#@I~O(FH*sa@-c%IX0PkMBcO3h_t((jBF57(s-b}1AOQc&3Tz_MX zH6Ngb7E}9R(%kLI<_#TNdNSH*1n&G49_=c3 zw0>FfijiG2kXO5e`&UO8P51xvdtm1g2m{AzY>@%k3t)pI=5tfL2lI~C)C$aa|J~Ig z%mq1lJ!1=lw0kPG$F&^}3nEYIu`ZN|P1!ZzQhO|@AGuLw3cGwKl`!(}}x+8FM^~{ohBWxcv{DCX?DkK2bZdQp_k z{yI3Rn=iHg@S^%$@JPM_GRJIS59}vX&HmNzQdcR##`vw1zZjHLa%QIdX-?GA#!t~4 z+=#SJSddZLR5z^oOlm%Gfk5yPN2myq)K%nC2sv>$NY&V&PrqCVDLpqw0mlGwU{aC} zMTMX&OLm%|70y{UbA4wJy|3(Fb(jlv5xK*{ZzN!7)7=+C!2!fAfsxk|=<>!o0DTrn zsWs@U2=!p8Ru20wM!tZ899yh6N_@Pn_Vtdv`jS=RuUhrc3S7Qu`mJ{F?V%oA<9TDT z;>!7bu?deVwOO1vbdR2(%o10Vkw_w*+P2-noRVm4niTJtqvM58&Dc2;k3|#{90E=f8U9&&H*2Hnpxr5xh4hZRH^3y>wq!o=my%}w+JCD3j>n2W{L z5>i+TU?;0_V%{5ZH9li*@=4Owvd>@a!HwhDU%aARa zQke|vu7vq!hZ<>{3PB`^;=2%25s-BZ0zsYyoA3KFLf(Z+tJ8_gB^E{2k4szjvMNqs zX-!Nm(ng$t-p`;nu@K!sNr%`GP#>k&61m6X`#2JXdyhWvatH{7t@yYvQDrvOoSak{ zsBC$YQ0Q@2OZ@tEPHzruw1D#w{Sc>8hpS=R@b0fUcMGWq#Iy-VzRb||3!DIIbLiG5 zESap$87wChtW$2qk zRj@VgS|HbJzrr8HsBpfR_I==@%iVi9=ZR;V`HWE(5p9*B(XwnGF--H*v6XsL*9jJp z3Ulao6UFLzc^i!b+(w4EZ-#v={90F-UPT3WM&`>5TtMFjU&Gk)%!NlsA;(QrUQfcG z5Alp?g{uj@EG&ZmAoB_=@&XDq1%$GAHupg3o6-9TkWjR;i}Oq)Gs*VNHL_zjJ*PRp zH?<)B!Nz9t_3Lr;Qyr5y!HU;*)9)W6ePQFMxM_oQZH_xWOe<+ck(=7)6yENRj&Cu( z;UM?l@0h=WlL4p3Ik3ef!x6c{t?GDwu{v$*U}-rJni#`=xBS_SS@%D|k0@@M??MAn zs0ZmiaU*GKBnEJz)^;1hdBoaa@9O=11E4HEF`Kk#A&fPlBE0(xq)U>ZL6d^f1NF>u z=6}uW1#Peg(}=pU($AHVjFtu!`nJvG4l9CI*^ZB)Pm!CRF)SxJnJ_y63SK5X93*3g z4$-FxPe_3#=`GU3XFR^wj3;1QSObPfeB2aRPnd;F#7oSde*Wsdn50iMqR~sI8*?!{ zi-0G!V0Av|;*qp#45P(dk?!m;(kST62-U1?v_i@_LMz$7{EQjc8}%unVJ=ZCl+ZhR zgsgzxfrrT@YJHYn^zJ-v(;W8CPA6(H)A{7y&G$N?dc#WWfh=@dKz;z>Nm%Yd<=|#@ zx<|~%=4L(cA|L28m3|?FZ1FgVP*>bspxjvXzr(ol_TH7_N6}!fQton_ zya~tOSp8x)tfB}-;owv8^3gbO_VG(Iq&fe*g_Kxu3Z>~u`c)}!^d3zkd5w^Xo0OeP z)uY`Lv`Oy!ws3kTOG9K65KKqog;LhlrPi8ubMrbbRN&mG2%>hphtasu5cV|53iFZ2 z@T|1NZCxi#(t7Dqz;xiMWwEVe*)_a{ExFR)5$-iRVl@VmK>7qvmOd2w4Du zlX}6qvaM3(2LchIwp7=s2xVV=r1DSZ*g*7sKs+QUS5_dlIGG-kKixSpm34IUuVl-k zAsOPj;GI?VU$&KLS< zv*FRK{>jM;m5&S~YS{`|=%;;~U*(A%YDo4+ zUQ>U#?+_fcBN1sR>i%!e-PV?z=5Y<>d|b*H3LyOAJlYNo0jyaWr2UD?zm4I)J=mN# z?@>XQ<~6ckT;{>;SVMN>>QN&g<@;Y|t+Y6+OWhR}Zv4;<_zsM#-Qz0ks9&X!>Z5|e zDt>>GMY(v#AQ0Bp>+-_imSL>=;0ZHP(Zr6#tG4j`3{Y3CoY7a++=5}I=#proAwXq! z4pcU~0F!J@b2GYn8})5}z$0Cj=LMQUc8ddCjs9uCqsr0iV}=7q!Dr8(UQl|n2B9!c zd_!v2aP|+@KKGLX%s$G&D;Ryb%Lc%4wbB!N1<>;!97=_B=#vFzL^cpWbc7m&^bWkZ z^Uju7z_1U|bg?ma6suN$cQ!J2dDYHVXF8JV-k51SRM9ghB#qcRo=BgD%RMdwC6HeJ zH%Ora2Q7@VE!L79JR60m9nYrVN^-X>Mi(T1^L4R}11 zz4K$nvt#mchgl&eYL;z`ZwG*qbLtj52VHf?m0VDcFgEByH3*iEe!13}6e_=SX~U+C zr}r3j%;0oFciOCw8}SY#(>G=fq$n5YOQ&=5)*@VE%)fP&}r z5hV&v)r@G9?yW)%s>%6h#H9-ZRoVKr^TowO$r$)%*Qi*UmvDYcq5?6;2HwtTQ}~1_@tha{-({KI(}T(og;|uMVa?0Dh5qQrh^?h#gQjh9$mLcs1=zC z^r9ywoRuBt1HleIsj5zc|X+PMydG=!{Yb;z1xCdzKonJfpQjLkc2w&s{(x)SUFCJBv zjyv8&b*$+5dHVWpSQ`<>7p4DoZG$y^Jr%W2Tga0k!sOE_LFjmd8Jl`}m15F9t9&W2 z9Yh^D{)&y2%Te&gsg7GJozVf}2xEz{Brqjhbh3Qk=7MAbQw<5OV1wH#^V5=VjL?RM zaQ0|~f*q_weR3BN$ZPU~#EE-URlc!7dL2oTfY-c~m`W{BQUu1F+Rc$h)w?||4mW`~ z2&;EE?P4yJ1zXz~;kQD{VzdiPfk@ahBQ7jpEBpGeR92(zqibGNoK7#)`IFfBiS+&E zWYs=>!8B4?>4nYrj$@8ZkJI<%%(NdENs<1j@l9Zsi@zNO_kC6|$adU3YLLPGijZ=lCW#0*k34!&&iqRC1XJURC;7Ba43m+1p4|rZnM$lNls4gwP2lp z)jzRcVdmCw9CKbSDP~s-H(ROVna35<0AF861H&&yzW5jxR)Y9#agG&sFbt6oOZ|Cm zMHvowBf8H9YW|e+4){G7`_L$cwmn}0-?&93j2+!8q?kwnDZJo738sy-^%8wN&9}~9 z5AtgOQcy6Nn76RMiKvZ*Y2U*>*P%~{N-V3z2uK(nP0 zN{i{d28H*%8#3+#vKteJu*^B=l$uzKW5B}_0M}qTO-m+q;06Aj=GmARxMb&spu`!q zc&nVcFu{d9Ln6#tPyJ4jwkb6T12w~E2T*r*Nt`yOnZDhNXsvj!E9Vm9!f(Kv1N$wh zXie1y`cJrURp$S}i4X`UmmS@&GzTV^ng1r%TtU^|rxLZehmSS;fK!U99@z!2rhLm0 zrPj2Mkbn>2;wJZI^gKBdz?H0Vd})t9E?n`zT4cV@SmhaT&sV%ry#3GZxq<4<1A}zS zyQ{ATX~i=qFOYpnY?_WhN!t<76Xd&#v|JPNAZZ|0ZqY9fSYP8l8TX%h*dQS? zuY#6jJRv%ToRs}9$Xsh`tq$S{Ka{IOI8Iw0w+|Y5j>Z1y|F=O+D$8mBU8K)^hXsTj z*qAI2!Iqg96aYyoGSI9#Zlp|B9m#tF2R43}EmT046PAYyFbpMo8H?Hr&MBMj>u6rnB^o=j__DKDHTk3$k46iE|+o`E(bLkxf+QMftr6YQO8r0-{VAB zznfvc)-}S%q|yoHd={(yb83S|15vxkp8uq~?*Y7mH*SDuTWmiv=)vien)7F(hfhHX zI*24}#{K)3sr9&tiL{CohJl>86rV61jaMxYOdkZe;MJ+SbV?>Q62#*+^8c^mxIlH~4@voz&gm#sC%GYK~8_b^)h;)mcH0@Hqt|}^Z?6B@v+T*U> zuiWe*t0{Be_vT!9SyaZK?N`-{u`#b~g8q=+x%I{v6^Fc|37{N%9O|G)A2~eCj7A={ z2-8z5QQUar|IX@MV@H-L|BEhRm-YNF!*)E`x+0NhACFdlP4qVl!Cf0wp}5U^+`azS zM(tf0l3s%wiRb`zRxiOE@YQ>sn{mHs3@7uIuNhPjVpF$_D^n`h8*+%)9*C87qEtju=K`CRQ>ZaLMfcd0p3| zuzDHNjRStp8b6hO%*KFohO+;&T_fo?28<<}&zYJI$&U!?e}kf_Y?$IIYyt};&l8Nc zRYyd#xJ2lF8js{K*7!`}g1^YT=RxJaw~5svsmjZ?9YMv_iXpFi^H)mRG!Qy~;(G98 zAkri&milR*=%+Q(Ps&(K5782clAnOK5OG7EypBMn{|ZG6@~fu)Rq(Xd83GrWl0tOl z-KI!S?Q4wu&gSKGgI~O^6z{fuOav1_AX*aVE;hQqjrC?2y-%Uhwq3YT76euTiZC3) zxid#cT%XqVFY5n43xH~>tWh71tbrb_ZqVXQrgVv+$~_SLT;b-FMya%5??ZFMzdDx) zd*l9<lgE+dueLp?bx$W^6ROB zuk`ZnTJ&Tm20{^rd;8C$<2#@q|9gG`q(b<3CphQGZ@sdl$Z;FomRzgcWtWF{0zMx0 z99ln*gFh{zRUGe-?Fx#DU)CQp>TZS%lhwrJM=|hrK3MHqxS~gz(<(5HpT3)K^dg}4 zT!VkSS@B>Pa%CT}>OBJRuHRqIQ~8}Q3J~3v?0~k8;=gFh#~+N(N~vsO!i0QriUE{N zK$?4LzWFPl(fJqBh!+GlDd7nQlueUqT#fubc#87xDrl*;beTEMX~peh4CT`xADnvV zZ$GSc$G%ir$4!CwgqTdl?IB!XwBj8S5TynK?@QA-{}q=Ley{!CrSqhuy~yt!a9)DHO#-0zzva7{L)tJK5@OmC2&S zf|QGVu10x3oA-cNM;x#C9RaPBV7dxR#h%no@Wcn#`d#Hj0&>+D+vakifYeknt!CV_ z&Ad2npL(byDOavCc&m>Yn#Rp}ywNWXu!`LY#a_H`gJ$SYkHMZIzDPMA4_-&oufK5s zHVRCr^AjH0_6Far4(kS041sX-l-Y0W_^l%Ikm1bsT+Of|)jZONA)87O&77s0z+Zx1 ztp8-UlO1Se$4LN-12&;=Ou!ZWGy9j6kJliP&mX7ySo@o0WQn!sO67|JvxLtdPEz{i z;bdjQYpljZeb*3apg>^I2N=DKt-mhThKDirD}QveCW~c%yxD8FsFcZAI=Pz>Wvkw` zzm4(~;rakna5L{Ii1-SUZ_l~L)@tQwfGj8cn{i9EHfrw`*5CfY^n9_2Hf0iD-<}}l z&KgDLqb5^u&}`1zQt|A24Dx)^+Grt90E}(?i6g9f-yI?pLIu;!KP^| zHAoCWo|8X+RGHeldqMF?rKo)n^`HhR`ZzHTsZ2=d8vHiKOeq8>6FK-64q%y&=F8xl z1y<5+)FEPq$)jeeQM#OE2QGAmP}42vFH8VmsCMyWV?ZdDHky7;;`YGgS>7Q&^}l0I z!r9h1_*wti1DJBFCdLRh)(T(EQ+XK>hlu<1GHsECWb&2=&a|Y-dr}uVg zzj;6Kojwk!b{H|<21|s(jqI@Jfw}G2*ArVs9K8t@RpwNN=fEI%DN4SWe2WE};wS28 zdMR^j&`9oEu=!eY+7=mqK~X&ZaiPq&rJ+%Yk+)7CCe1nv+*9a>dt^T1x1G-Ko<0if zl9JiHe!&6Sj%d`&g>ifE>dVt=|HD7nXY5Mj4&Cd_Kh>Z1u{WI0~14b*qge!x7}Ccgv*wQDIt%j-e@#Zh0h6^N4{#d z8Z&x*)Vf|TDvT=2Q=Uh+Xu|h<`TPMV!r)|c?>7p;M%8lv${rtnym_wM9Tn*p5K}~$ znn^o9i0MT-nr}kTU#0{R4|XrZ^F4MLz&6b^|f57!+VbhpBr!7 zGP~osAP!#ITbvf6PKBv@$@BA;yi^RyKjk%s1AT)Wp^(kVYcCd-YDp$U?m8rm1POT& z%|c;mX#D{-4^#HGqQR0|)R@LmD?@h1dlIN|F8ue_y^|AmuiL z3EBS=e#(Q=)Gif#oulJp&M_Wa@DvHVwTq%qWMUZ}+hlvb8gts&V(QVTa67$}+$?TJ zOLV|#a~M0`849)23DW#YB)$VJPu2`Y#??bmKkner^}XkitH$_=h=`n}^WvBaY)ODO`SaWY21&boDO!zmZcB5t zYVr3F6l@b0vo3l6_sX#``BR60LSZy#%0Y_By4|iLj$29MW5X_99`|a3qU6@>U(M-Z zmHOd)9{f^8p;?3=9?P1DRc1JQ;Thz2G8VQb+g_!$Y7N{350v2i(#*F^IzEOZ+JJ~8 z{Y!IAJbo9c-mqauEG=q{$7;J9UZW2GR*E}qNSR-N!KXR&|2nHx56iWpeK~N&esaii z)Y;%;d>`^$zw-KGgRHSfm6J%kUft=Rtf?iP^4{rhU?8`la@<;>rm8FaxI(s;A?i2$ zuV^h6!qSwaesKL*JES%|&d(RZtj5OdNRfR+>Uk0o$tXFpcN|~5o5gLS&WbIoe=3C; zy=Uj>;lQus;VtI1#>tb$TAaJzv=5*Z78Hzr1^NN+rulY1q1Q8^EQ2h-H~w$Q4{089 zJqzc?66mu0e6MZ);dX3k_`P8c5`07={>lvRg+ZRc@?^5GB%nKo*JO|CSel59g#2o2 zyYRd@tAFrQG+Mx1jFKhn1$ZIsK$FSmd|}L=IQwqc>MR$>4^=Lfvh(VyUTN(QZRJ5v zbz%MNw(CDU>PjZv_Pi$4e@9O_a`?=E64~nk>v#4*~bE(wVed(B! zo16<69kCYf?8H)_OJGC;;)+ROHzNy)EHhY{-Rx)u3c*W2p$YM|L$dORMoCF2 zK1|$b%M-W>o$DGukXISC+13~|J9A&jUg+%n`;YrP8~Af(q1!4!Sq}t*h*OF2df;!4 z{vp0$O!P;fMk1x5=$#qT1^9k?SArrD*gAh0F8hz(<|@8JES`mI9+>+Hoz$N8<;gLb z61BVH+QvD5IN!5-Di2y#&pZPMgF#lyAkO{P;uM8XlZ3Qgkl>1Vx%6%IzLGA{&ZE(%-mAZ`)`N8MWmw`<;2z{TK`B*|f7ZvAn#_mGgg=ZDXKchw3_Jcc5 z)O!&Mmf$1$bh1Ml6{KSz_`9%l=RTX@co7?*rK*zm_NOMaIh@_2{eNNjNPum}y0MP#C>}SVbASBDb zdm>QUqOxdbmsGtPwDje)x&v7R(ck09WA1rw-X>6H=%slyyl_F^HA`ZueGdPBAcx(6 zd#l@hHGlL`#LCX>tAw{`z_BmdKb&QXpU$GmjoN&4BfE=zyfGeQ`)hk^Wji( z8UCT#)(w`Hxv$lBqlfTomn3&V4x)5%Jx>kErtsJXm&OF!)IP&=Id++ZNZ3$HU?mzb zMGZ8=&f%PKZ8no-A&nEz@iTUDR8=ampr|M``_s*V|TFAQA@(z0W-W0{$23!%MN z-N-sMu)cWr zrs=VGWJIG5f25)BN-4V$WKqVSwWnJ?jUp;5LjV;#`U7k={Ndz*@PEB{g6vz+zsoF` z31GLj`@~-8tf38`d!I$&wr@+*Xq83-%#>~EH^qj?v79SGnl+viZb%Q>Af1O zm}X1GCVqYL#{DM>y6yMlf6JGMsASMGu)A5m?|k+`5kB>^k79imlZH> zQLUM#{PNxB({4bv6^TW`XVSDHOV}SD1|17{rhM)ezVsleteh->nGLP8GM3aJR256V#1-C3H(L*a z5fYXpFoa12>A3w`5B0O}Dh~C2G}#u;@*^x2HJ?#5MnQCK^jnK_i^bmtu zi$nNn_b0B;ylY*Bhx{HE)Uuc~c>_5t*dfkmvMz&0n^M$}u?b(g_SC2nfR)nku_y zRJ-4x`-S+)9Lh1FsCSEYhBOxcFf+DK6ArWeYl-_gUU^v_t(#P@hpigdT~$b&nzgVp zVUu&o%2M^*V0AB&=Z7UISMBo`s9K()0@ipT<@q>!9__dKw%#zWZ_VYA2zI7Q!c4j} z5P5b%!Qj`y&Fh9i^di9rsGtF7BS3a@4$uz>UxPP$dwa~prQU@DJ}-BT3$B{RIMXkq zY#DP>hcAMoeH7>CV=s?vo*Pm96JwlE$aWI9OriyNl8}Cc*%P$%SR)>C6U-i}jUNX7 zo02i1SL>YMl`I#i4NaHP5SRRcROL z2^1bV>s-AXue2J?(7TW8sfJ16aP`I79{W_jVGR`rI2gd9mYu7PDi2rw-meZ;?0Mcx z;&idag!O~Hb&gwQg3Bjkc`uMTB;9Hjc}}Nhw!UBU2~~OmpfWqTMx-FVsaYLJ@jdU?uO)FJ^h7}_FCJa zQoNI^U3A#o*e;j9)Lun&jf>Ruo^$;2jc8(nJeeJeCfIpr!6nOs8=p)_?QrZbF+K$1 zjb&HHMzO2vpZ)xH9Dt#P3?Vc@lJS{ao-7LK>+<<|Dws`6D!W^r=p2ews zQ2A``sO{P+=CWli{EdHGI(<{t&$)+x#{CO59mOw@S(}8zUMxw}=WXL>B)~xS5vVec zvzJ{6%N0+_ST)4d&v|s@bKa`j>2DtWJ@%GeY_KUIsM9OAWY{13N&FKO ze6x>=>4ei~KjK}y_c0METoKn+xnnq5o!C+_!Aj7I^rI;AMUn;6y+Yn=?sVk3!$Ytf zw+ZS8^TY3e0VPl#!91A(!twozjfj_9Dc>gwHSuUli4rnSo2(FUu=%^V7cs|(j0gAq zTjzc%kH=NuvS~NZ$sSG5!p3S+AP@=+u<|&#L%9KW6Leqzb&|XLoS?t9wLX*|0#PY1 z*8N&0*Yer+4#)z-I0Ymu-XZXlzV4bV!%)4AXnstrNKBel+4+A)%Yg$|lT z5rdMRkkE6XXfDu4YE}1af!M>@Z*dTpzDC##tan^ea1unF}z8{#eQ3I-AR1|DV=!gI8 zyLLu?)dsu($ipnpSeMz`!uN;<|2=;!!^WiwrN}|HsXk4`MY?apEC9Yxw$+H-ZXCN}P_u%x^C{9x;HeK)J=@<+3{I z8*e?yf2?;mUz2XxjN2byTt?#-LnuJ-7kN-Xcx4ID`u?r>)b}#bky6mS&IN$En)CgZ zLM8Ezf=?I0-&zl4d8rQ9F7C;gpUHI}W?b535_F~gLrsxBUGp=8b3OF;#o za~J*+0}P*IikR>gu|HhbhS*=}4h}nT6hWeLORF+VT)6!lfNKGGM05b}4`KukO<&9E zlY=hivilPJYv<#2;*!812Ph;YhKGlNpg3iBcQ>$6>pMG($Mdpj{9?Yk2?SO(2%Dzh zYG@_=l)1b2qs>E+UII_pE z5RZPJqpD~#TlPEScUc1}QDL&zSF|y!5xoPQlPJ!^d9XBTn7c+!wbI%k-7gZn`nOG( z!T#0X0W+ZQb0>=P?!)P<79yAF=TDz{{(IS3y1mg-3v$LbCGQ$0w9qV#SY^HYvHA6C z;uNM(H=)g9f?ext<4$ZGu;IMiY=!gh^2CFI&80vu9JsFik24xYP<)m|^Fm6XMc}P# z9%z7nQ1lVYJe^z;RRTM>3v#k-`qyQP(L-X{>z9-@JN}zM&##$|y=AF3Q3^;%U8tl? zj%aTPS#ogUF1UNk;s?G1MI}!Y*)cc-NpYrrfJG_w#U}cJ#uILeqKNrp8ymvLXB&i1 zNz2{rSLnH|lL~jy{?{U34EY|mh5Mf*2Sg2)cvUu;Uv}H(TTKzvd|_l6O`cTrW3(5_ zr`PZw&fjx_&e^rOL9xj4xFN2Fj~0^M_h0k>$`e70;J#@EWoJ8@Grpa#qbqq74aKFL zZ$rv{na}+B*?#jV1u17Bh&}{Ypb-qmMEORYOw|P?;l>)3&`dQ~-1NG%>JOK&PjigU zaIFo?)hONP%@fOaM%Q*QS!Gk-*PJ^au+l0spz=gEl{O*^-${yvVbD}%xe=TLoszTwsnr)NqPZ5_F4GY{sBY5 zNaWC+4}VY|-tK+Q}{us z*?Jl1@{)E|Q^y!WBjT~g0Kj8{X+OGhF}IQ^WL3T!1>sw0B$YI6nnY1X7_$@$=6sSx zrynEkY*g?p6bQmXR>cJ8VFYEUBoLGoJ7!4>2s@D(aFrp|xJ{4L^KwLiW8%#q|F%Q0 zOoh`Q5r%pxL;RGe!a2)E8@;H|IbNxD&GEQkmEqnm(chs+>|Zv_gd+j=IOg@@kTn8P_*S&@daLT;nzkpF^kr9l z)X5tsqA)hQGlt=a!m<$qEtcF;-W*Oyj0J{+Cs@hq^Nbio1WM;<*U^}BL~+Wc*2R&M zCPdSuWehy@<6sK zbpq#T!8;VIShXd5MmUfXzLc3OMXOYhq?J0^MB>wLM02cxqR;VDVFqEF@pL)NnDLV! zFYggUicP8}qP2-;$k32Pp~dmt^qZbQjBytK_y7J)Z~wZmu4#n#kaNL~RU5P@49shO zAS?$wK1Nh>pgtoQ;Va!yF%+L)2>=>lVA5?50ydARgM9N-&Fgln=Wbn`NwKa#`KLS~ z0=4>Tyf#&LG@>iTK@Gvne}WMdp&u_Jqn<#$V|(4pW&>klzGqhY1I)gUC{a<391;p3 zz)vTUZ8>eNJlrI?CIWM2P_lKLr?FJh@VKD*(0Hsw85Y-s~%XL z-li7}D$=Q`aU4a0(Nb_oQo<;NYWV`X5K0Rr6+rF7`>t}%w#ZZuxK)O_NT2cU&R0u( zgSQO<`%EIO!q!haAC!?;($58$R-OKs*(yqQEga8x__xm@!eXP!jBaFrvTngF>RA*$ z0gONYj8|dCATa~$Z*V&wcUoO{5PDy6;W8SRTi(_ziY$jM0g=uHUZG)ymLG; z#2Boo6hK6e;;3lJ<%DT4+AZ4byEmNO`vm&sEo%{J6hivn$`;Q?=$S>OQp&eivb|GZ z{DI=552qWhC>~vK2h39z)AA{Y0ZKS}CAnER0ZP;C_}8w;W$-?Q-}UkR3EyjO;K6=2 zU+RiaRBJJ?lAuNuat5M@sHMJ^3#OcS#SU-0vwr%2FTfEE9ms$ChTWLpn@N!R6Fgsd zuaw*jYLj``dhipHjj$V9M#e+-smtzT?sMaYPn!?di>GbRCJh=tSBq*Z;8zB!6907~ z0MTNH9Ddi+UVzvAudV{km%x}?DK z0Dv!5$nM^jeR=gjg~|W@{k~hbPB^_h_V`CrMT!5#CSqiAT}ANIx4gHeTg4ojXVdI| z9=vS9NZK4PtSRC5P8>tFZn*XA{g-<_@7-58080!cki01iO&9ZiBbBI_dlZ|FIc)|e z@84cSahPlKzkE#=4L=aDP%jcgLf2LrhiojW?r@gHsaA5dmdlZUh^Q2qy~yKS=|3QO zAOh;U-htbwe`8MW3{k(OC%o@#mEAU>{yTl4G_vF^s1#$k=!OyJtMa1#NiZ5qd0y8y{$Ml$rj0^!Q6J?AZVm2A%rGz0c+vUe$Es;V?8?%g^X4C+zdj71 zl+0YvdW6%YhqRPgV6bxEHY0=_~*r`fiTW4)&VSGdpRqb zTE;T^zJxN5A%2dPH~aX~ZNfUC3zs#mt_mmYKR)QPS zSmDk>E4o0hy(adgDg@@B5>A`2k2oM9p+pt``Q>jO@*2Y;;%|*mw_jKln%gya<-vyT zLf{g>USJ4<%~JbKm!v|R8Ub^^c5Ntd6U=Ndw=WOuNd#{xdt={kbFR#M-*9<+uP6u{ zg2Zsz4WOsxvHrULsNH%i`NWQ({Akia}3@o2Cun;239I zrl1YMbj3d|j|$6*GPG>aWkhbVZhZw>>uOr&7?Sjqog62GCBh%ZczDo=GPicGjLoB? zjGljSasRIGD+Nj)91a=^Hh5y_{nv3B%K}5ZUf(=Km7bOxkj+asL?4O6pGSsL788wn`0rPHC_9WK1PMNAdhKm3 zjmZW-mIZ|P-z6spM^IiK`7i5@Fg@YE$P#8U&i|qrkopP`0?d&ZqBxe~%$ePmHYc*7 zzj87Da#I1mLZzz#&z3jsdcY{wVGQIyTqN`t#`?6w9L+I z-#7OxUZ?hurxx9JtvXW3gm{Q!L1dn2t^<+(buX34x(lLc*s5I*F>p80X&AnY9Lqe~ zU0gr&Qtg3XcwFqyMnlPOl3vCUd`rIjoj!^|Hjc`J4Y^Fj5w@LO_l6*z$g?Z#cb|bAH`owQ6mqmCygj6K<{(Biy%Otd zCI0(35jDwKkDvH2VYBGU$D)Tc1O!uw7#M18S(IPo#BF5A2i{Y8Da8WX!G75YO;E}c4Z{*b~=B!x8gzr$#}-Xs!u5=Yg_9B zTuTDAxorA=r&ooEt>+CzryyWE4QD!7Di2mdhH^KCOpxSm;QhK(tP%;1PpKraWW=qEmK7w3 zNdhPB|Fu#R4PltdD`d%l0;zmZLcU}f1R73&xN@z@oN3UovDb9z9BEh0BI|;%^>-d5 ziPPA~S1QMb#YX*$lc!Z93S`*R6<3ry+s!DSnphO|{kQ}8Z`pZL&lqgXU%R4ycdMbG zG$HuSA#yi&saWg^&zyTygl9`yXNO@ps(na_<{2DDOKk0~jdH@R5ry~#qg|Fl<8bz( z_UrRABZHL+=FN+dRS>Cd*I~nd-{fdd)UExTiNdD|3H0w}B`mc$IN0PD?p-WlP%B?h zP_oXiBi8LHW_Mnyy0K3=Hc@qVIGQ|AXizT8seK3S|kHzqfqPZz2l-g`>sH_Pe$ z+q3{2ZesAlNUTOk#NNf?lp(}i95F(%>N_I>@+$%6hmH~Y2$=N88scy8%B4lY$+I+~lKLWZVjMD?!fQ!i zqAB)t*wK-Qyy55BP;Y|BQ7P}CAV6U{wC3+quVf`8p3fPkWD#V{jz~qoY8xZSd~oH% zS+M>azguse`*@0f*jA?Z!xjbqaU+Np#iw3$s)QWv4+eTZGa7Q`ofc{WUYCgn(S<-G zA>{;~8Iz6#w=^_(RHx%HTwo#0GchQ5I>tf8QYfU^1s<7_MQj2jB4f~}@*1-4k zx|2=14n7nfrkd90*74#fnvW3Z76&RW-TsEtUJm#^kpJQN9rDHfUsd(Z6S$s8nprfv z5ID9{QGo?rlkVBDL5J0;SZJ1CGPoFnL=r5o2rX!`4e^eXX{k+#&4Lm|)-K>^(~6_) zajN9l7|L>%@qThn^V$w>i5|AQpEXWoWoCN|t_DHG$OLw1A#kmR*;KDW=ba}^K<2^M zkGR7XD74!Z0}#Ypk2$YIzBiwJqX1Yb;8iPBlhKjBNfdJDKlt6^@<;Ld)KKA3*=h(c z2s(jdsK1|rri6yI!I(b`GqKiuS76HFbcyvwonNcAkA|AuC3VZ1ME2cW@Hby1;YgWi50w>N1j#A4-*_ap004XgNQMd1hJfF9ed4#frv=80Fl(-l zE}$ObvK3!nYT|jaxx&7Wx%Ihtwu3yKc8J3vnQ8hO!?#1tK2;Q-;&1cB4J*A-Y@P}l zk>1>`*VM{srYY$VPN;G2meIQTE#_Kcc2+iqsBayM3Z{tXVvAh9+ z=WLzDq>X$c+jf_f@)zq(p?~cvO zb~nr52pFKDdhpBU6HfN?(G-RxbZ!z?w~R_*7fJgMlD{0EeqZpzlG!NH5U>8U-KhdO zuT!*xMxc52!Wc|iZo(R5u_?B(?L|l~X&&3ZzK76Mx z7C^oaQqJ`z0z*mrEvV+_0A$<+arXZ#txzK3^8nNE#LllrSw1DD|0ZGMM83Qr?PX|{ zg2dw~##IW_MQ9+%Wts>$QezNkR^y=saWZKXI3m0l3kZIf0_L~AxVQ5Rb&ko3k05QR z2lKy~*qU~`%eC)5fXOC{$6+@5;q^yP@kRIwL2h|opZk_Qbn};qYoOJ<04Rm01xo7Z zjQ@(Ze)NpC-agrZM$lYb$=PGqd-x!DYB z0Ms2o2E4p~zrMIUZJ278R@FlScA<4!4|4`X1P&( z{eosh0$X7)XR4`1>Fh_EgD#1e4~9z`ylvy|)opwS)XRJ9K{yaD^ zOimGgBtqUV;F)*}<8`(V|1UV+4|Oe2>{F4Yum&|B`9E!wlaDf%?qXFpy z;@Kr_u+FC<`Wy&bZGQ`N874Q-!cbp$@rzML6vG=MI0*^3mf&rjK3-$E#{h}ryk&E> zq|O(pL)qtU9a>ue>~Z5IJ15$?E4m(yW_@>Y`Y^r7eJ>iog=x3J68@cdCAx}`*1^~T zKJ@?xEtobGj3uaxDW(Yh7d3zMR~I@a-WS@){9FV$kFGBU*5Ka#E4-+b8?X$7W+bG} zeE?1&t1awA)<$;3-c%^b0#{h+I4>%CuaQbizZbEASD7{7QO|!NyH_JI4|{Ix_TFE| zW%Dj`=GJQ~O|axmrZ~pnuFvKT=t?K70;WBb$bY`CIFqu(%c|L@8(&VW>}q$MLWVei z!u$%f|KN4^3+)4={o*7zVmUHRq!TUk>z+=6ij*%EP4lT_{);C?H=s0T|z9iVapq#zxuOQ{i&Jqwb&y_WqW`G`AWBa}o2cW#qFY)icP8VnY`YX{H!D ze*-B~N(!?YxB2{;IlRgE^YVxSxZTp0ySv10D`GvokAF`Dl%k2>>KZG94xJkVGK+8@ zRdRi1wiW;L!e%GjvYsv14m!U0S!dw^>fo}2qJ@hbCw6{hqHY zhE#4asZbKAP_na8p>MzN_|}~3QDsIcjRlmFBP;ssH~>FYYVgxdi-4I4CpD#(rN?i< zl~A(>-QrvQ0GS9LfyE9Blv#0YE?h3(V|$@hU(?2+4sw;I-FN-{>Oiajo*0awx)>X+ zjo%L2MR5d?#?U!;-I~d2CgDMxPq|0ufwf6S&8Frlle%shs8QxGiU~J$cJILYi}a2B zKT;u7CHXu+-v;hC55qf~z3fv0uqLQ`NpOykTEiU#B4MAb7nR3i zdMiQfwIZbqlDeKR<@-rs5Yln13R#Ejk{FEM`@4?LBG-;9Jy*hDmt&WCzk-qaLi1w^(Km&e7=JrcuRpl3IDXFTeb~Ovgc6v|))~XZp?3yG-;n6f{sVRvnYJP# z-@+Zv6XGQPi@%Mh@h+5r7Nr!=qWII8bTdJnAZIWq9(A?7)P+u1*UXpVz@L231@)=U}!(nLNp!?aaj?#O*z_{43czb{UX7!x^)ko}Z(L-pU zA4lcxVD;eJ^lRxV%wp4>{?Fyyq(6goJ8q{lHHLS87y|q#$2t9KR!{O9+9UMTtw2HI znVT3gSS@IYO8uO?^X3^WMn%ysp%*&hCk`B2F|KC> zG*->KkM@<}d4`4e_cF&H;#(4^LISK%=*vLB_*cOh71|AeZg(k3Mc2$lKro*M zi`Vtd9bkF?k$WGv@o&YnMkw$&?x_{=`SSP3PVP@mX6AF>q;5xy>#B{-h>V{c2#8j( z6`Y)<5#`wH?hQV`*)F$YnoR*{P5M+(wC|gB-sd;;_~g%y17C@>U_w!I*#L9c_k7pbqf4oO*r-guVk$k?bbe4Ja&{_Z#cw!#7` zhe6^q9;^uw`5ctI1tge8gVj=Z7sLipmLk4c3GaQegr3Bw(Z+<4TqGvdW(@YY+V@@Y zH0O88tUX>_QQ16gH0X-CYsx~K6qN_mc#OqCQLtm`t%7Y zU|QgdNJ^1Z0txWKj0ti;#kaAY5ZV<{vJptW>q!De zqii5Svfwa$dBQ#*qGZZ>q#?a=n&7yvRw$Fl=E}VK!|{dWGiyKCnM3HPilrYcM#PN@ z{xZU(E+s0u8=PoxAgB1{7Fkh|^V0~bAM_LUWW738uEq3w-iXZX$ruLd+hr&~JV7_K z^dOKyLMmbr;tDbIefjwEGw1C?%nu&h>KdP^d@xIcF(QykC3%Y-e7Abg(9m$xfc}hs zK!y;c41(Xs*`KlIa#(#^#Tbq+{wWoFbYvkSlf~mobf)l`Ry`kq8}}WyqzW+Qrj~DwVF!hb8z)ptv@N zRb&6+ElkEgiRDt-UMeuQ=SN<&up+hY3}U^qJpnAJtZV|nCt~~b6#Ew=!>0%xdStqy zDcBvT8LnJ0OgtAAsorUyBu?^$9#|v_h2HdHFIN@+@knnlyj+Xe{k3;e*ZKk9P=gD` zrciH1H`A5=)F%D2U+pc{Yy~gi>@fWH4Gy4>3gg`gjWcC42E&BDR+>>oug&x1F65Qs)GI}*Ft?O;*hFGjZ88PBE{r$8U}4SI=G~obhBEscpS@ZzE>d)3_r*J#=?r-Acw?^H-?~KdrBAni28hiYOAkfX-eSrB1C_L z^ETp6tw1$+uVsV1yT0EBVj7t`>@rRZ%u*1!hGCRkxH+X^XZ0x=B7ZC_cV!wMaw;T~ z+^j$c1Po*ae2*>?g-$mZKxA2}w>jx0+xbr5<9G>ebaKXX_UWYH;RLEEliF)M{}Q&& z4zV*k#~p;Q)L_iM;bP7$8Df0X{y~jTx9cfh4A&P9JS$YcK^Gw)Dr&5R!&CP|jE>>E zqZ}&Y5(`0_ZX+zNLM-JUR9gLvA(f6QZ1@S{W)D=grO#<)Q1Gm8(1Xyg3{5O7AwoFw zno?WGD#(83-q6(RB&~8WzjUoKJH1O#J`8meG-2BjFYB)E47LiKJf$&{xo|Y~! z!B%%^m};7J>kE^BZU*?XJ7n9A zGcN1QWdtN>Nqpdv4FD0tfpmh=`HBni*0*ri)DSk>B)A~w9m)?j{~0EictI3~CpNMj zz+f8^N(qUwmFUM#3(=J%PMCg;R6ZrQcg7er|h9GiV4&sAlAptSq&K{gfVk{?xA8JwUD5sV_0+qV|2Md-T=gpfV{ARKu~F_v zDUvyl9|~CuyDn0AFdPW&iyq81z9;tuH#^TLYz)2sO#_u%B82?m(Lbk2dSSUV>f@=C zRTB%#RnYD?*mD~0eS}ZDrk3vyQ>chYmQt8xQIyKg?azfauh?seN)&#C*sP|dWr2G| zR-rSSPqO8dvL8Kz9~Df{EeK)`>l~Wc*)SJOX-&@Mnz%hm1^Om(H%i-DU#IofT79_% zR)^JSMMlv3>ftn(;1!K)8RGAHETZHzMoUYS-bAW5R;A{|I!w!gDB>LaGpvk99$4B% zqu9qQW^;(d%D89Q(lv1y#^axTsrQYwXTf2(Hp0sOUrHh9g>gvaOUPfo@s3E157}32 ze1;!)jM0ILncGay3}0O9%iN4TQrDM%Sa4`nVA7g6o5(^FS%J2*wcQ>J|A@>{)Zz2R z!j^xB_Hm>cLNxM~1RK<(h1Sr}kd~c2JU_3RQ#ZXg84^CmU1GA&IkPwff}8z_bM2Ag z`Fu8imlE6|@c&)_j<%v&u%j* zP>LG{*?vdS*4AEHTN4AmpMf;mAH>&rov#|w@DeI+3HC`DRB(m%q}a$Tw4hgw9i3kn z`hiimoH*j`7u1?sX|Wb-bG-}LGLKGq{_~b>ar@~RWOxQ@UkkM(9E_DwIGbb)vM9ri z8$&~ZAet|d@5@ze!G1eZAclKNU&X@Z0O{Mu?#C@|pw13eCXb=Vq^0Nk)T!(VA)&9g z;MF@a$q(CuLqKJTb>{nF)H%#M@-!3)MgGqLJ!9EovhW!xBqW5DLm+C-sl)-;Mq!AY z4+Z}o`wVHZnlA^Ji)+rX(U`cqlrRM;-L+Y+S>uU-*gD8kTUEc70H__|rm}pBl)he9 zYn~Vsv8KPIPcVheKQZ!?s^|M=VUm!Pe(GT8v?A@9UCV^Dj^2NRdZkn{rc{UMsIPi(%is&wL@6ePSYdG ztb^Q7IFzmdHRz<$nVyszY_=HCJdNSu)0d(bvoF%HolE1j_`Bu{)~MX4e>$R_{u>Vd zMuoSySok#~!cl!rLTw!+PnOf&YSnL$zC{S22Vt4FI|yCgs@Ck5wY+p{9+*wBU#R^I1HX< zYTEpAq-iTndw>4(PS~8cHM2Tnug*0srHHmKv<~mE=v%jo`l$@$ApsIBd|VN2kB>(! z#{YS1)A&FwEiLiLKm_yMJ3t@{B17+2iVy-uB0e`IWFMvQ&L8RNk|0SQhd*#$!a+Mr z@Qdvjf62xDp~eU7=p=rwS5`XSp6k8ykGLYY>GjDLAdS~0$4T(6mc!JP8-MwaxA>rP zZNb7YNkA4eC@(2lb%&MFrp%?Rd|xQo+A2ZB&+h}|>n}%MYzHFsXnBZ6wy}i+W+q|g zlAvJVcKkL4xjOOSuU=yUUsc|*K$v5)5*8;NYc|+l#7AVy`VI68S}^;1YGbUjUO_g> zzZA}Ubz4Y!WAeC|Ds3pn@$0ihcY!|%O_92ssx>Nw#)~)`W!#lYDUEMBY-#@6nhO8Z zBpXKGbmekd2Hrqf5n847!x*_zCZMgUAfV!X058r)h@S+f4&^vItA=nw;rS`V6%ZDi zFCyv4f`WmyYD6xy+*bvk}2M1qHBLYhJJ(dP{Q`XHlvJn-*GY0T%Kx)b!!I@pM z7IcypnVN+m+Re#@#W&xd2{Q@Zd@dgM6@caE8BV{tPtJgpcW_b zXi}OD{T$IA*WGiX_!pEK_MGOwS?UTeE=oARr$tX+k;doVIv9eXMN7Q{wr#y({1upiS%5Uu& zV1BU*sCNvCKBtc1&-Mq5&sP^4E-0=s&2`Ni5+%5P4MdttpR$KX8{pit$xLDJ1?*ue z5mnMphs$s>I0@lQS~zFRjXM_x*Jj--EA9L$6x6^h)I~U9PuWtBd3!gdI_~8Vzv&b# zi4hnmoOn84ZSp{?RXocj`((6Qj84VSjni5AU_nSFg}T}TQ$u?TcgJ`+yVgSA1uidP z^$CTv5wLtBLP5E9lz~BIx%6k1#~6~*MtK>%_)!{^0Vs1g7w%J@ECK>v$z}y`YRyoA zNe?7?T=XmCI6+*}=5|AA3rmhDo;U9&yJq2C0Ew%-+@FuWPbClNJ@=mVNCmT8KR)=6 zyuDpqjSiq2+jtYV83ig^Qc4?F>UBzOOtxLy{CMbCKc5K?52su?Pq6Q8W`OG=d6^!m z0(wri<1v+>0DuKCN#A)mgn@y{2x!A@GpJ>B-^!vOlM$*qX!Z751$-WK%0C&Cp_BZ; zPNcSYuw@E4pU5wm<)7w@;Y~#*%Aa(eESm_9qY)U!C9yt_attYbA0!Y52RTwz_PL(I zM4y2Pjp)|RMMPBZsj4^_S7C5v1mk3tP#Gmlxth7S|CPjpBUlC5qqVBIlolpX-S*9A zi2~I=x-Kv^5@<}U7yoy+PZ>cWuB>XzvbWdN4O&+SQ#D)T6bj(CTZtvSlY_=U zD!}u>pp>N?T#uA0$gT|6L0_w;G$uOf0(FGwoRZuktA(7m-%Xy1cbxwjENf_OU5Ho z7trY3SJ*Y%;zimq-gYlS;4lB2{mHpau zfnr)hOQE$X2hUu-3cYw8E79i~i&KjD@t6$+YPE3oIwDR+B@pkYm&(@3%#05eq(6i2DLo)&XLHpRxE-|FX45FYq^KX9dUbR~~8 z>>6Wi?TiYP=4t3?#I2`cjQ;J+y>dX4-!p+aKY^0tW~D)Jy_P_ffHHzuCK0e>nlMX$ zNKWd{!iN9kn_APWDovMMOJ~ezsX8}Hn2Eb!&Ff(T@0d~7nY*V^{Df^LbD?F7UFg$g zqj?ESieffNA%g{^)^ca8b*}jFskGR@EP5X%gby>+?n{elJAcae5G<>$!!I=l3wC_} zbC-Fy9U_?cZ+dE)_^(|QE=AnH9XY!MgW>a-pPtN2G#*Wez$t+%v!;dI83B9|T*(yE z06GQ6q2B?WeGZz^&vG&`GF+%H(n7`=b2{hDMX^8D?#Cr%+dmA;8LTT}4x>`a6MjOg zL60+~S+8(ULXHjm_-n!EySgVAFjWGlfkn6{EI3%g_#lSj>SS@2Mrb9kM*OWIU?Za# z;?c$QA89u+_okPV1I`;T#|W$o*-A~8Xw2W{>=N zy`$2&Sc-{;pfB_QB_%KeLJ^HfWKieMtEe<_X7RaT(H~6Fs|!%v-+SDT%}((jXf{h0 zx*Xm}tJqa8EiJRnp_i5ylY(}PS7qP(1SWGilPK#}bJAr=*@;fH%UwJ(aCQb&xpu_% zcvEA{Ge1q|meASDAyPBWexqoSAM{P2LK>)b^L5XrL>=%?gmpq(v;19W=K&LHw-Wlv zvv^Ajr2PZR#|$OBC!FKM!g-ESQ7Yw6xVwvTck&l7xq?-LCt+BI=jeo>!W;?F-V-%@fhXfHW*%ojx&1<4(K#>$~`$ z&6O1ob1&-`sVpiiP3CW*vnS3D+b{5^=|6_%&&!Oy@3#NvDz5-|3xRWlysm&AbE4yD z%+@Cg?|(p7rtLEQ0aelE3&Gdr{bMzGP(HiZ6AvM@2Fhhpflbu`a}i}QM76+=8K-I6 zor!2w8A*3TokKO+PlU+?DA^H(R4c0*-1dKdCCKSmpr+6sul(&# zN!L*D*D6+}ri&!VSApS8?dOb=)%TEX7lI`-AiJatSx|@|+g_S+MJ^Iej1)3Q)W=qD zS1HkgKRX&U!*O4Y?nC?$?a}ogIa~}ef6U{fyK$&?yRI6%&$rnY)LwUM@&S{{Bg@ zmc;u^^ciUfNf}Q@&o_gvfi5OXx&c2swcth{2y5y`z?6;4wew&Ste)s3W~x* zSQ%2NEnHU$KO^a_6cwyp9kgwikSUqhNZCQblrwlohDZA-ss?!OfB}pZ$?$=&FR9SO zHhKUGSvZA83P7U28cbCD)7RsPfve8kuf{b=1}F?^X=!{*N3L8ov~Mlblt=*ubBSL* zQ!onjQIB}L*uWDKX0{$plgmxWeM0i*iBYcMX6f<-fRyO8irv8P+jOyq$4v7x2JDk$ zX{SPs4#CE<+Q0Kzz_H%$4I($P>Isf!l1LDx%HTA`4d%7HA?9yQHn>Q)^>ex2{UZCm zV_SV_E2PNH0jL|5({q#8I;_YVhDqdAQq%_aXMYGLf91dj2NUy;D1QlHP$#%hyIrdw zx}tXx_!|9pyh{z+!X~C`!l>X-NfnpMR}XozQ5)?v=f~i`J6ZH|@k}*utD6HF@g^c% zuSi{EIzQt9&19=cHgWg^4nXKQPDm4Tkqb%yF9-72;%jnTU$ z*g7y9aN7dcjx0e>gv`v$Vb6r8*CZ_J_fxv#>^L55t#1A6sCDPLiGBP;k{Q0|DmyJ*g+ECnyW*V?7SN4crq0LSk|UQQ@tXP`n&BmV;tu*n7jBGpASt}P4I;j=+f%yP zWiqob{_DV>pcqieGtHx=`d1rTU@hPY6e6;l@t{ zIjm7SMvlqy^~-EW4l!J#njIW%@hdWQzY@_IQmh7_wUVXSD9J#0aHW!resJLgU~C2T zvx45N%bnlLups0r80G_0(;o^ww8x7K7*0<1E9ysHm$0--scEFyloUl{r+tq0lvE?qBnLWHv%rKAj+ zE@yMTCDd-Wg`)bhKRP*!E*uY*#E&xb1)iROs^?DEQy!AnxBIKVvdlj{6IBW=LU_V4 zZwkltu_PTkNol2aq*NAXL1LV2@B6KWu5)zF*tsG_hIxpbaEEgWaquAeV!irAb^4FF zQC16Ov{Hui-?W?QFbba`))tXA3Nnp3euLa5<{T#vOTI67Z@Y@`paIGPAjf*Eg%*VI zadNFiXi|Zm7PEG?h*-Sf9g+vo71IbHr98gAO6$*0{K%@k1BpK$9LE{ zg}J2o1?=T(xp0Ze)$`DC9W_Q5W_~*0g?T*Xs9$nqXg8B%56@!a<|6Plnkc~Cxx@_g zcQ_v&Ci}zBAOpGcLu7BLz1;own0X!HHz%M>#>m;aa>-k7GJ9T*LVe|fzU`vr%7fbH zanlmhfYo2QO0UGkH<9Z*e#$mo``f*zRJMXVf!cTS2A>DSrcaFAT|U+@+Zh4sBO3co zZIut*pWR8;)AcTt19c`N3m4g0+TfSB()~P?BLdC8G59=CvQ^L=@Nt&dQb|I0G`bPx zTV4438YiZsts<)pN>0y=(GxRwxhK_|&ty#RuDRpKJe#ML6_!y8BM%Qe0c5@OHJt%K z?{ar~CWc3_nyY`(tQct6%VxFt3aDy8?|IDZ(R`42p_`P%p0`p^l@sq-p0PtbWZw*h z^v@qT|8w*G;op2EVbW=ZT6FDo3gL*sM1X$L!xikIjZ6ZIVU3JUkwNYrdm39s$6A&B za=t=qc`-%ON%}#MzEK?@4=I|{pxFO>rZ*~OEJ0{vyMy+NIvD#1>%FgnRcS^p&+dox zuWol3s4>w5{MJTRRw&H}y)HUgLf!=WUGEicr&lA9KXY)}JvwCm>N)*eMT(H%19$UgEnv>8 zwITEM_u7A)BXo#NE_cTOF! z{Q;T#XFd|ALjA8a<7nvq-I)tWUgj2fH=VWcN@`=h(a0=6u$bkvNgvf9>ZWl(A>3g-#%zF^j zY?kr*6y~0aR_or+gYxqyL~7=Bi{sa3h_v<=1%mmUI=@F(#*9Y1QTyO^1*(+mJQKN9qm0~cxifWYq2U0EVPpbLby$G~PGVM=j8Io6f(VV9p{q$b+wn!H zLkLgIKmN#;)BB_F&K>`S2$AIIHBqz4PJb|p+u`cwa0`itlmb-71O>ug6uI=5zY4$N zFGdG1p5JDOclcwd92gKQ#A9OB78hrhSNh)q5$oQ2eUw(kG73w%kJEmni)IwN?d(d! z87k4}7KP^QqwF2bu>oJD9BW|K6{1S$Z0`BEvkIU1L^Wemm z-&7*|n~2?=%4zqbaE(=rz+;-K=Nlr@b%Q&Wh_tWB-xg~klLf~2oXWmNn381)coU4v z%Hk2?ixw=OexX|Zug%)=hrB`q?{ew+%`IA$iT*8Kqn1Xe=2-d%5{~=T{puF4_uiXo z<<5&q09hFVk&A9I)COf+=8O2=6 zi>6l?+9G{g+jAs#Y*-f0KHzaV261t7BS=Aw|9CH|QU7C^F@YoW(1-p%bnx`_bj_JH zs!H+vqF9YgvuCuCN15DrAmv2+Pect24u*HnDdf#(5hDr$mb+cOsfVv%F`S{%1dwzJ z$mh0atW}ihk)be--z*B(>Wij8@$h4UL@0t3iV9!CUD-`umfSat2m%{y1ks^3m3t9_ zk);NJ&Hnsy06?F-;Hr1Xjd_9Q_XM8dL`4Dr8sFCwjkekV(}oY(vOOsb#(2bpo}>4# zq1C{YtNE8UhzPQm^+9J9I5rhzTRd)CWHhelV%g(NUT&??7VvNUz*_}mdAL+;T3VG| z8WTCXy)wdby_#|2T$~V*vRt!sB^S<<#Po~Iqf6Oh|Jtt&E%+z5s4|^STSNDjBfqAAhIx8iyCJ=<)bx7_qzy09Yv<^Ez#cBtI^QnRHGlfI22^tz)iY1q2y)6M8{q`p3k;Sys7#2ms_*t3i`-CO4p1gA)R^3Va zQiB;fj~O83xHxxo38m{juA~21%G7|y4MhiVgFx&LFgo?zHIVDV!&=+ekjL!ECir|! zSJ7A8ysvZIh9U91d45RseWTsAKwfPoOJgetHx4ocsyr|ru|`viAR3c#-#%!h4Afh5 zXhrM0uYu1zluxhPmgAk4#Vvky+sGm}ywO3F=RzaeVzYvzphz9&`EbCluOdBjh8a|8 z*+2Tcb9&J4-?qC-7pUF*Hs1cd#TOp=Upk8zbd?D8X8&w#;gC{>hSO|m2d_W5Rm@ZL4)xir0_$iYQA@k zO%q#MGVe<;YDQFpk*^7VLZ(bIN@g(*R%B_WBr2%l5S=Bz)$rzhs)5KNgWNbhk2B8y zVA#q3=B%e_-O}Ifx5saU|D)-g!z%k8E*@^?WMd|4YO-zHwq27w*__PD#$>y1=Hza+ zC)a!C_dIV;f8TI6&R%=1^|AbYMZ8VFd$uZell#mTvF0Y}8(-W~;0 z^gR;R|9b(l4HFgoqh!pqv2ry<8~>zWafp~H&B^hrm#?;{=RYu-U_ZYE)1PD@lC4F( z8`Z(FW5S{ay6(x%Uc?;E=8H{XV=Kb=pL;T5*NiJylYBx_{`?}J80T_ACRij+(G{aq z*bW_5=S~EV-sU>33TTMvu;1VAF|~9%BFf997xZY2*x*}BXQ$NPyUYJLUZ}fEmV_iD zq!F;O1A#bUbTa8Afsf}3zv>G$_N!Z&JGMq!c57pvvJqzn&&U>-wU($owOX%#!zCL1 zzdYSA(&4u)!So-(e6mrOKhP1c^q%1;$ZxoW2;36xI1($$g@~TucR^iTqMYOru0h$+ zCNRAadqfecanT!Cr~a@b1y-#%e9KIAxY}vb@qZD&-?)6aIl(Gjg*hD)Nun59FzOfq z>Pmt6RaeIx|MUct8mJucd{oMSWWhfFCF$7ZcJeoPq z%pRZb?~>DB6z4^h*&d@AQ`j2I=H> z8dMg|+V!epY-4=wk6uo#AA&9z&ye(rKu32%Z00dqYnMZ$G=7)-7$Myee7hzEw0b$6 z+CvvaCm^$6ox{8X=r_-bl=Qr zZwEPs&eiIP$opf>i2*80WzZVYW(=H28$_8aJFz{uB{sJvL~x%FroX3*rcDrR9tlDi zCQm90XE-85@g4<}6jB7`LHR2rnh{wu4P`cAJ8_z17$SWtK^Ap~b6-AbR9fOf(MMLR zt?vGD&~#u^2SpWKG=4F&>~3NLb?;3~Pfri@2GLn*|I(}7(Fc(?K_o|SJ>_f-UA|vj z7S39AGEPYljR4kz|AC)I076S8ePt3jtpwvIskpdj-k|h#BijUpx1e-XYCch84-ELn zwvjedDVkn4CklpHryEm>D)iDJ%{abf+Aj>n;^j{<7#`lP$`K46ipC?xAMW;hG3G@DOGO#Wovnt=UbFm{BM`fo%5H9Da(@nC z4p+H;u0~mB5_sn5J-W?}Wk3DnRLhTy zBRRmJtGm4nKNO8w8~5N6kvu9g_=z~HrMt!6bgSF1&K~LZ*0R34yXM{gV?*t&187v) zdamB;@7Q$r%wxaQy|)un4h0IeKcVqIlEw9SBU|T6Gg~H+#fc0G2O2C(ZofqI!)pWQ zuAgGrBP`(71)VzL7e+!(1{>_CfHodn0>hchzok@&g={bwB4pHo<-xyt;&rNjMG+$L zO@De85O_?C-$pWggaVwZU#F9ze(PpsecwxzyqXCK2*1B~Uug-EV-}JU|IfQ9jwUM3 zK=JjmcuG(@Zi)X=D$_iv5`jDT#Eoa=#0@}l|A>s#&ky}P?Xr+1FQ*`vuK^s_rVU3{ zSBHY9T*mwp=H^y$yosb+O7FNZ@KOd53Tc?yX)$LN7fyN`%yH8y-f|U4)S2@a-lmZj zs?b&Zmz;?Lll*;lL?}WF&=Ez(cxDKe<^nFX^_IKN+IMBfHj6{8$$+X+o@+Hm8}>uL^U$P>2Y_Hx>+l_-2M9?h|F%yug z;P7#lFvSo;Y*iPCb;yq74MB~S#3^ja6vrJ@R2lPnI~mDP^UYIyl0eD`DAEziWo2Mu z0#@O!XZchu$IsR=z{_as?No=;?IdT>hC`3}v_#rIkm2p$-3mY!^uLh2@*{Q56xl=e zqN*+0x}80D+kW96bdF(DKo2AL6%4$5Fnjp=xc0^2iiq!PG}){`XiO}#FobGg}@7ezg=Y}C<*DGQkwB@zO`#8+m4b+lSmLui! z!Ok&ARv(zS+D7ZqKV4-?zd|GwAI}24k6)~RNmg*+!A_ao$aM`lpjt0-KY#d zPvTnEtg+W08gNC(vtaJrX({2_vxTg-yes4b;DutKeylbf?X|tPY1|j8l!;~$?f#AJBwz*I*+E4WXnoI|fqq<4sB}`EP@ST9E!1en{Idy#<^H+Yp8=^LytP<@X4AP$- z`GFV(NSF*WAn7x*2!*t7WclP8l>;&aTUMdKbEDEZX+CwZjO`Y~jLQ_6%MS{9^e`5O zwtF1k%^#t?+rn!akS*~KtaEVCg zTmBcEY+S)*2!gTXX2d)Q1exNJ4GVF@Ej@iH<1fdR=RBxHYpIbrNEFslTv5IF$ws6j zQ1yHAw%E_B7;T+y4*%{70wJuL*Zlex_rY8Z*)wEz*Gt2n6+5VrE83d3*Op zXwrrKpFswmE$Xq}IeW0zgYs=UjB2X#Z0gONIm|XS(Hcc@i3K@^=D9-YZ;J|UPLMgmT-}!q*a4;n3J68h zL9aOG{S`#uShD}!lzs3x6&|;P_C)4ktMKiYw8ihNLoaf-l97oJh#>7W6txFJH-0xy zfqyAFUeA9b<-~-nO=&FDF(YEF=aUZ5FEZ$}c}oH`Z0<6;a{$pC|JQY3aEy^|uT1+# z#ooI+8E`;)<&wvKe&i>0#u~VU8O0*|HvNr48u8b0HqGMS%{b?Q7V|SFeYBLMendQU z7t5`(0hScpb3`jP%`la;ePEdhci;>C>VJ*&{nBSMTB0b3Im+x-obh#6P$1}Qz&$m}BDw zxpZg3s%=AzqY2@#MqxC>-6+r>aJshX}Dn#b^h$zZ&fYUkeG5G z2ZE|2p_+gIrElFBIzBU}dQ($>ZAjZ~tGw~iMT~TD^hP8$Ta-fkG_y>AtC14kF<6GcGOE)Er#g z5m)>>axmRCh;3bD`=zxGd%L*=mB~YOfe5Jx1+K=Fwo^7>*_Ntj0yf)lrb0Vl8kk%w z&9=C}!4nKFyjz2KUU=Q}Gv4{fPk3*B-DWq|MF0~wk>u!{T#&7{q2#MaJmG3@xHGInU@iiApm<*^EE>HH zd5_v9L;}_bp+hTVzhux>cJjt|T#017>-OO_i z;A^xw1KM7%C|;xT{=?&KGoVy1?w8)k(7^#!_wA_XOx5Dmn4&)hph?W!`s9=Sqs_hV zj=aNX=@R=sBub)>e9{{c?NUxRrFNH^rw|`?QQC}0#lcA>coP9!*sZyhoi+D0Y9tog zJEdVJdDT=P$_yFzPK9Gx`B3EV7?jzXNfAlwYC#MWw{ycuX&bu3HzIcfH+)<*aO7MJ zy1^q+%ZGEYsy%{lxp$}R1oD8|%LHoAVQSw%wHp!c(hzN&6)V~R2E`AEZ5FhJhS__+ z*S%B#2IPzSd(#8&H*q%#fC+}FSYQ8|wat|yRT0^*mOj4`{ip4x^wA{O_;ILFob3H3 zmo&!l*|GzgoRdy$tZN)#lABq5l!;X8=|1!tBGH8p$}t^S;be_uNX8O@01l(tX{MEg zMvc2gr*N&Uf5g8=pi|>B>8%gmtirbNK+-T39`MbmAPK>NT>rK#v1;^q2HP*6{+*g7wXdEMeH`BMhX%U)pl)JIj$Y;sy+n2h!%bD%a}OPCD7$h z-+(ayw|@w5t3vwmI5JB@B7rA`TlxlcIrsP;%htj7d3L`LhX$c7*Y~y2gi5p~l>StO z8d*5vv}11Do+FvZ3saVjYYasv!-4$Nq&QgmsK0NMYRTPde-x~$y`$1W1r5Dx#2`79 zx|%DycDs!oK8t*k732>=#ymX#jq4~Yn|?z0bHzp+vW0YTk{b%y zF0I{!2%fmgn=EyN4%2-{8&WG!(5TnDx=M$GbKty2{M*#Ro1nw z6SG%-;UUW_qsCqH){!t)VypF4CMN7$An%X%iDZ|=Y+3q{SfesD#91!hSA(zWY~>V_ zGe{<(&cS^2o`?7o!tmlr&{_UblVl@tv&M39OGesz-;&u_(06(^Jk?8P^^Xa@=Y~J@ ze7uPlygly57phCMRhGz*j>5StoOYj!eB2Ly&-bO zm}u5YB1eV>b;sv!iK2tHy-;P~xyXmqb~7UgvqRufQ4M^1)YqfL8R41GOI4taANDBT z=YhHU@gDH;pdt(`Xb8fUvxEI$K9c99t(^e=H#Tp7G>+7az-$&~CT6|`f!3C8|LR{o zwyq1cq|O+m_j;G`6WTjq%Rd|(yjfg62gn4IRHz$H@CIG5OdtjkW)6Y4EC(PL>-rx6 z$IB&^T5Jw(pwKV3$%U&`hMN@(rm(_WpbGH$N?f{AYfgKfZ)3nxy zkUd}5uSP!*DZ7ZqKj1uCyNc}JpS&+t(MYoxy+M|9Vh>J^3Qs}b``K_!5hz|2ydzW& zvsMp@`1GRv3lvKsuw1CJ5OTDk$K=(REz1w;zZYPJ+a;p6wbjzn8(clHnU(&nQ!Psq zxTycUNP+g|$ZjBX>B&xGpWvE*`4Ulhgu(Pqc4ZK>#Q8USh@{=gi2?hlg5>f5tKh_j z^T<^#zyj*BMVDV{p(WOPQnXTeK&m4Ms9y1iK{fVmip?n!#k1#R<`xLmMLQebf$nfJ zvcVHY!R@~M0uLpo>?U1b1es1H^C468b`FspB2Xy-R#Z?hF*6ebi>0Nh1yk50Ef2#9 zK9a8kw^C(`Ha&BVeRu=w>qK#HXO@rG@d2UfhVKX*EiH&l?G^*TKH*RsKD9*kS`*J4 zSDdeyMz5`}xktI=rO2_$7Uhx>fet5%ArVmo4-D$zJii0h#}J=Oai8x}W4Pf~ zEty>ZASBNK#TpoYcuWSJH13kE#i%Y*vv%zD-SyX7HT&zH^3?v?L6(wPlf#MG_5D<- z7*IX)eQmCXz!5T-5REu^x$Mi8A3OvmCgwlYdX8eEtJDYYWrl096lb~moPjd_-)HgL6mdr7z)t6VIOWhoi&99a>qD4pgOO*0EC zm&zWLYF5Ebm(h-?hq|)j$*^~D0N)+Y1B_z5AT<(veA;%l^ORqhaeunh!_?e3D?SY1 zurPfA`Tv(|_SkXF>VF2(vr~5-%Pobpm_~Ae7{~ACF6%E3m3tU5qU^#N0n=`gl~5Fw zW7A@lS<50Hv*X^+&)+nj$4>8~X@_jRR~$VVTj-7cJMGfPJ^Q@aTV+M7{#v zCob0mWDQNtXrW5=KWvPZnHlnbw39cR^n>T5H5BpOW@g6**CDg$oYGG}%QJc~GTQ2b z(4(duDc;U=C2=7R%(iWKt=@Xvmn-ZOn%AA1^V_i2DMu!iv9RGif!)K4w1vF_51Ia2NQI2Hxu`}>{x2EGlr18(|$Gx4I_K*D% z^ViqryxpH4_qG2(Dl@0gCmk50H(1JepQX*xw~(NKlbsu{zMHo`$e*m%b~s8pqYe6N z&$Oq-`e>U_#;{+WI?X4x+(Q+q(FA10IV@FG)yH{7U#Pt21!@+7ZfI+&=(u*xaMI_; z=Ph3pH2+iGmDLrcL*es#?g0Q4rLnv;dLQG-e@z%ze0SvJb0n2pECUjCQB62on3e^a8lqTpLT7yl@{)k&DU8T>f9a|N(jz!d8Ho}Kh z26vAWW$nfL}r*SmeEea zSp~}&L$^ris3PeS68OOifzd5S3;K;;QIv;g6;h23~eYEiKzyadZT0jZ_ z4Cdp)1rAPI(f@X6JVHWxp1+1mf1HTmgweMFVKpNwYe10y9?QUY2L_}JTJu=&kx!&x z0dxHz1s!>`udHZ|jE5nutgiqbp3e%VS200l*Ij(KPyn92Mw1?k|K8~>2Zytt3o2wV zS!wr7^(ibp8J4m<`xh-hdb+NU_e0KmTqp%Z7=j!HIO(KdAnUe1II!gp|FL^&I52)f zXSbZX73KolWDj?mwaoi=8X3_0C8n@wcXwA3OaTdkQ|6p|O2zJUzWHZfTj6ikEnHHE z;{b9W0HmvM{@BFX7&5Y9vug2_Y%ocLPNqA}8ezQu&q)4cnR0F*%@LFN$Y9io-ey_x zcT|zZ+$oJBY2CO7vxcOxM!HJck?ue;5pFn{bcSW;?ZuNiVkC62c6C~`AQLw!>_v(A zQ}$6gPYgUGRy*Y|inJF&{^A7(L+wm*6`8ZU!0eM3K4!{LG&bm(T{3*>Fmi^ip2n4!xikNbEc3Y($jq!?>Z)Z>M>)Psr0Jcd! zE}-R7SR?j>>{Negxc^skiv5eL^DAnE$fw(L63&e6?Qy(tjX~cs7h^2on6>9djx5@g zCI9-~^#FFwdqPG%+lU5sZRRK;_`c_7alV_;FORFxh6CURH-pKHm==6fz~~6*vo+NJ z9_33oDM%8M=o5_nc#yqvwxK|HNr^epdH@8#9AYI}PIgIXi7h|g$oQEHASMTZzGcu5 zJXxIRo}9LLg+e?6DpE1t;<3Iiu&(4LA+#mW^)hx;jUp6m%c;L&!6K$l(1sDbnQJq# zccq$B)x+E5hU;|INZev*l@1Anwinp1!8X%srQrrr5&%zYj4i95e@jlgzX zX|UstViWrg!VQxlF2Q23H1aZ#BB3tN2ARc_i;zhGh9`W{UsR9;N`M^<082>&+uX1G z(c=q`8L2-h7Q{`WJ$j#vsP<2K=EK5UiWbMZ>8?!LQBG=pSHL-b1KsHiyfU=+mSs-9 z>XIy)*;1Vf=X0HFl-7E(OP`(=97pNsEEb>r-01psufFekf4IEtm_XT>3zAb*GzA); zq>@14sKo#1yZ+MPEd|(T7t1ekrd5s(MmzuUXV6cRsl%#0S~%ZCumIVL#ZL zu`L)Fc(LBZz^1mG{BIB5hueLnDY=6uFLo-lS+L>y-4q&qYMTLg>+dc$%Di&LUZFC6 z{v6(0z)GU%o4dhytw9@cg(Tnha%sw}ME&iwBigf2QIk}F;+z840^6NBjP0^K(gvDx zD&RSkgRBRIcoO70M8=NcBKSMws0Qy8|;-O}p!q&(x}!m3M++3PecA8wC-Y@9t$ zUZ`t)e0xgu=)Cdb*7}v?mqxeTgX~Ns`(8`nYT;GW8&s$T2`JT#meb(9v1IsHArB^- zo^tjZq=XF)={FfN{v6~=AG=0O;sy4se7+n#w};vs{K>;_LEl&7R*E^)G3yal37fo` z4FeKh&peiQU2^KXaTZzHpE}gH3w}1qs|&n!spZL59v%l*(dFqfD)CJZ054G<7weJb z<+Q*PHWWE#jsAV&sSNXR?+u8i{Qn{cA3%*@V8GjQz|iVyrmwtApDThLQa^bD$v0iMbbVgs_1Eq~{bpfAgR z*Ft61gL%>^No4Sq5rTTr>TH)$eNR;Lh7T`0(0m^LD_lF3z7q_ru4eqlb#DC#>gjt* zMJnUY9h8QLj8^*2j;6bu@D4oOj|r*w7~Y7@0z!vgh(`$OV`(!m}bVLzbo#g)~po>UV|G2Fe=k7n0ov_ntvQz%+xdPeQD%eAIEh;woK!bF7=dq& zR;Z{2y`nrj$&d(x_k2yOj0=2da*+LUlL4&U@WY9e2!+fEe@DjWxF)_8JI64{mprs4 zM8;$Ex)Rl88yh=Ae*M@pXUOKS1WAr3HXK9NK3uf(Ru}HN2hT*dR?rGs-8mLsP7bQ< zw;+)-Y0GBNnYSY?6}i0iRPua0zhw#WyCNDxErYq3guaJBggvuYMEOz)DdE}>Jk$~E zD}DSY)|)l%o{c~bOfSHR34Hs3r4BsDxFs`xMeMdZ zz9pGA%;@Rp^hZzk1dfpSVSVj>gnD&AYe_1ZY(!SZBa8U_C=AiFCXNRJqI}lbWO10* zMU^!1*{r~3TmjaIz~Hjnq*u2S_pyR+mLS%1!sb+BLvkExO+C(yoV=G zDB%Xv3{U0o{*%8D0aBYK3s6?ZoKi)W#tMW;07btPpz@&^UHpgNq|3;yzL0k0^@AC? zmiq1dm+$h|zI{^mW$fJ3AjH6ZB7=F+T#J9U>#KnGt$?@=|J|C;G+xaFI+IjWx%?ru ze&?s(9|8N}!7$aj1hM;cvV%JVTv#9sPrhu!b~`G=L|XO=B#q(Q&|DNne847o%N+k*4bO|Bf4z&XPEl^!+&6aZC;Dxz4!o<8aF`)0qb5&UgzCsgO?|S z))u$aWVcQ|k0$Ln<~WKkWYV9glVEX6X}^CKPiV*{mocRf2075^{52)CyVqW!JcScM zMzGrWM6aB4PQ~hY-n}vj1YGD(2GAZRgU0$0oZaBeZiP`#Khw0 z;zOPn58eR0k@^ZZ;2Jk0ix*}2-mHI`6~2USS~oLrluXp2P*8OMMFc+*^*<5G8COmn&O-I21vxl0qPjmlYb$6DgK;Dhc zZ`ufoEt-?~!qY4N06WzEhLRJBiTV<#yf0mylV)Gohf4UV4p#$o^9>w<>)Sr(k|nN^ zx%PB|4X>`*!1I;u81h)K$eV2Nh#GZ&o7>Sit2yI1B7((8^2YYbI9*)VGu`I*T~Hx2 zYyk-9M4mR?bc5~8G&9RQ&VXnYuJLVusrJ|h>^t)F0=8gThU~8cv9*PdlZnxpy#W}|p#*t`IoGo`Gvf{4468GgE z)`ixXkCit>G2nR~sN{UY1p3{8(=V|cErEl*!*(PoUnJZ`4{2?W2T_YIG|+9%MYCsl ztOs|afB6`IAMa5_d6Qjm&}Ia6bAUzUoDKFAxPtWEi8kzY>^^m1BVgatgTazZP|DLqjdXVGFRMUIuDA!9qJoGLz@BRho-Evt!H6#ONZ4 z``U&N>{bsF3{ZVyltQ!J`Pvshv_D3b3hvFZ6m#EE1#!~0Bu~=wP0V>5-;^uhf=?ljC$`a2!PMATxxMKV zqHr;+WZL*=cFVRVUzE>c1z*L>lEf;`N-*Hl&1oY7Q-T?j%xQg12~AYFP0+a@I(ZyMp&qLVISUzR!J$hyb#@&Q2+y6WG6@t2JR3|70&ZUf zZri4Jib&sRR;x9R2c>8MU(@y5rC^lf`}uEX&Hz~UY3PEqLWsjU2Bhvw!)fbf-gm>P zFOzdcx#uKfF0f8<*@xRA7kz2djJtRLupE-k+r5x%C+uRz@JxZ_V+cemJ*0pj!{?6J zeVI-iu{l87hxF&u1CmJsq$z(JZh9Aox&?vvGF6CdO>Q)9=kp0lxuaT6!UQUbL=p}R z#3%?wJL>rhF9cSU*37zreOI|hVba`JB#5=dS0m}uZpI(*MM2fQ?nLwYh%3emcBf z0MdQO0LSGgtLw`8s*0uDMc6KlIFFY8e^L#Ld-$I)?y+?QRx$58#^+z+tB8yBC zk4Ry|+e{}ws1@(Blbt&PDf9U;el}a%#}^BWC6hlF#%9{7#^Y4! z+dHo{m~UX<%C%*-p0Nzdra<_6u@OGKt#z?#1Ntx-u5cJ6W)FWoTu^G3g636<&iJHE983|-NzsZu zp;@duH^<7^4|3QeQ ze6*joTD4@Av1iR~hsY}B9j=tI696Z>vSk}5KD3%I$Koxg{lBn8BBzgXt~R@Tt_eL~ z1J1hsr0XrFaz66TcX57(D^X#Uf+B}yL6Qx`qYUlEL*`h)>lknSvABQPO!`uPa{Yq# ze7bK?Gi)BxcfhI&X~K-hECLOMgpNlcbjxQhF-SZ$gJv0l$@wMhyn!}mmthy?XW}PL zhwPP?v#x-F{fyte75!da5B^Ct_v8As*sJMz>Ig5Q;(T;m8&RL$>(c-?mZInORRAIN z)nome&W(GWDPTdRe*LcYDPG8gF<5XgjzFAmMPP%nH|145wN_R7CM2Uhq01 zM`;iq=6W){?}rNxE?;(HN+*$Bx{)P;V%dhe-(LPVT7vRkK`#$y;;yX-{dhMDkkynz z$7IK77$1fnlzc4t0!q5(+&z6?yY?_%Nr5hr$JO)SA+D8Ilo&y56Ha?q#;+%uJ^i~q z&)6R4t1zEwB3j1cvdZn7nA2VJ2_0w4H>SBwTP7(hm0(UHbPYeih*S_!0+}0+|9N!w zz`ls9^XKOuThwp#Z z8xzc}6RKjBUr1svlk?$Fhp~G79|Qe+PCXwhrZ-I)`boj?N9NvddW(j6AD55ZCm5q| zWg*Tbq#s?1!*8f~0zV(1X`e#|^Gw1B8%Y7p85OW>0vO(%-5g%0qZ#47HhWG?8FKS5 zh02hIrgro>UD|YPGxb6`%JD)m>dX9%3$jZ&ku(f*b)5wslv`@gub-n0#par7Vhzjb zi1f;nCrVgChWu(&FBgc2LJdG6oUp`L;uM@@Rc8i962Y> z{pMv{v!++@ZJX42AeJ+*w46TylWYg7!{faFtN)WM&~Y~KPw{SG3rbs!J;#b_5TUIU zCLyGFpEec{`NJ|iBzLJfnO(}xPLQtWg7Cfr_h5Q2Zwu6ZCU6iiJwj3|W)I$;F7HyK zy(4FBtwaF4ju2|7@yXYp+rmpK8s9)Tc{H@UJ4ltUxU_1kekrpcILZZDw`(#fl@xKs z&#}r60{Qag!+PesAzBOqDv~!o-Q6q}GU7W=V=>N$!5Z?q`h(%&4NWpZo7C&DZx=!R zm6^&9{tRT}P)K1?32bMO`G4#_OJkU6BT|K8Yq%hA?I3*bueQR(<+orfVwG@SN^%8U zLown=xF*9Z$hI&i6~2O>BXkenEbi-H?Rubv_2gedxi@YXEZ5!->ywS-x?V&ptn;K4 z;oz&j{M{XhPw$HbtTabTa`m@xD1tnr4ONHtua{t-sLJK4;fMDNA1(JucA$Dq;*SqMA74xkuLt6_ut+3Aa~!q|2pdb?H{h5?~av zPt~b$pp_Mb-o19BE}3R?OK%)2e%x2QHA+CwH@ibeC}v&xc7KM?+_+GDduh4V{ewx< zvB1b_+obSi$KOmFmW1|*rFJ^kLaGs@=X6CO40c;>1W543Qpq6eq+rT^=R7~KIT@-F z7ci}7cksCmvnjVDdpo^cSuCfB01o<{+VHjCQ-h+5Nz0qc|zUN0;twWJYshL!`aZ~Vj!46;Q0-pBx^w|{R8;cP1a0;o^y z1yqyOYMiF}amRP|+lo*IM65R3<@Ak#rY^;{)R{?FYGiZaa&^iAv#^S#Uk^U%k_IsM zejnQBZ~kMvB*{-*V3a<-)LO|pY68eRBB`sV5tISDb+Xk+4CT4xN7Ho}a?l{2n~ptO zc(~JqW>3`1MHiZE8dKlVXvAAps>qU^$>qhy<5<8e9Ld}MSAcj^z^qVF?3P0iX`}RS z^$l2-N&XMCrVhm{B81ZS=P*0=LNRDptR?Wt*}7UH`W60Q9eZ;7xZu zevVK<*Cr79x(*S#Qc*xc(TOfegzPJxNCB|On$&0}DyX%eixm(c6+v9)1@cq+CeRT5 z5ip0!HeRi$k;p48K9rS#e`C=Q1hm6{cD}U1aeLJ`B;xYxLx{Ft)(aH9{x?b3tiHQc z*+beFzX79Yj|{>k`wxolrxf$Tf6RQQSOc+CNo>NI=4ne<#*m=hG#`1NPkY(U6y-vV z+@U)=%K!ajMPjv_8U)l%X4eC`V(Yni@Wmk|`tQlpB8U<-=GyDA@!!k4INX6GS?jIl zThoO30>2;HpA8HidKzL_MsNAxQHS*W;@KgX&uyQ2F0o*Es&N#u`62;5(dcrMf0VaP zeLTyq;Haq}+X}f!m=Zgsg5e$u-qnYevZ7P0bRH;R{*j{pHMDS4c~8Tyb~KtcTsdD> z^8V$I>K=qv3XkcMI1|sAb#)G-Cp%23$gii|M+L2Kt$sHg- zp+M<-5h(Z@x`q8%HF2%E>Z6~|zh8$#LPFAc`gc#5&qX)k1QQo&>Kx5Y+|WJ+0??Hf znTN z@Z)(I_`r)kZOa^#-MfQE251&oUV+WXy!SiH@8IhZU<+1eBlx*rLIAA*&jyo{jaZDC z@}RT@rt8;)n1@0Bcu6?gV95FY0U^RLs<2G=U9l+IN*Y8Fc-?s%UW)e=h^u-J0m?M| ziXANu@3Ill2^Ld4x%D@EdwD4+x!5OIKB#af3iiyAO=hEbKTv{ZkWPSy9OuR>=$n8k<7Py;XaeU`H#TelRG9t`;-!Swpz-F7Zgi4O(ikdki zZk^tiWNBTo_m`$*`pC?$qRh}Ai`Wx;1j_|L7DB9YL!xrAe`g@v`RK~nZ9O25%NfdC z8|2>}StA&DH;&jQo0i(pc+)^fUWrkmMstH2#WzwODGjJ~6Q-WeSl4!){&g`OvL1Z9 zJW4vA_m>;SGa>T!pNluNdoUM|ml-RgHHK0(0F0 zFI|^AH?mCP${I?{qZqumFMIQf*P~zJxBK8ofhJVyfAfPv8cJV1sPK!v6X$Rs0SEuIgkT&FVIG}Mtu=~w0IGkNISS-i3hy{YjVoXlbQJ=X^X#GtJ^t6!|0Fo5%3iVx{$@rq{lP3Gt0P&*ec1_wbv zpqsp8ur5}B zHdUy_CA(hHFxNNFVvctl2ljpF1Jhwe@%?^v?@L5HJvn5DjA2nlZXOL_agZvqU;Z+O zPzNj6J#XxOv&#bG4i{QTQ+L*nbp7_y6VGnDY_gf%7RX|C$esD~O`+@Wv+d(7(8!%` z=sgBi6efgUZykybE#3_b0C2TM5xy@gem$z21U^u8u>B)zX*=)zDbM*nRkMi3<&;UB zmMst{{MtRX%#s7eJv zf_zm_WW)oDXA#OVDz>x9)g#j!=DDU%92MXMs zi)Y@Y(0_-9`Q6jISForppg^@h;E%sfV5FuT?Qv6OTcaF8QO6OBYNrVoo4c4ml`7S&Z@$GVmfABbtctX5Ra9J`$fdc`%A0abBL%T9G6m)&!} z=g(u6f>c8lRQ$SuG4}p~L0a+V$?Qv2V@eK!GbfUu#}fC_p|vwSR^>F9k$5o29t;)^ zT}kuLAz5+7t3-g#VRE1;Du_(Qw+y`>M3Is1UB=Tg`kdldJ8sn!jmj2CuURwL1C)nt z53_R?&Jr~|zo``dH0N@@q1aq$`h@oSxK;1GOVzZR3|y(n*kYk>bC=!0MSdW4{Rj__ zp~J>2k^;e566F;3Dm4b#)^?D5+{J%H0Ob)Fp)5_*)O}ndfIWd~jgjwqFZugXUmp13 zvO8WP4Um~(n^~%xtLajYoi~#PTkusaFqNv(Ng24Cb2gqJFrocZ)KqD_yBVeM5Ek79 zA(oD@`oJwEXe#v(QjXw6)zzzazsKHmCrAPEylHiW)rw;;hCsFX(9 zM!5qzKfDl+4s%GQi>oCoHaj6~qF^NEsa`LW=2^_0gIu<4D3wGmvknM6Xm$=(B?)3F z#nADn-r$^Iq|BgZRTyD_?yLQet7aU7jP}Ku^_oHUyr6HaRfbk{D3_bt$}sljghXgL z+;258$QcjYrY}jRCc7=(@Ae*pB`z>(zrhB7qll}Xk0l&#IXJt<3D!oI-#jsD*nn~@ZoU3NcpVb( z2&WhDc8?xYxM%~XKBS6?`TayNuYa1<7yi<53l)qQA)^uG!Yu`y6+blVfl#fyx?28! zEdln-Ff@=FRa%igJ-5VF`W-mhjR-c#a~9Bg@M`K|oSQ45hJ1JE2Hw|RZZ}Yq2X!bA zSVnb*{$L%u7*;Ep_PehuBZFj=f~LQPSP3XZ@GXPl4fedY@0KtxQ%(jTL*0(-w9=Uv z-KQZ<+Mz}Gz5!$XKLS6(#d!+RXk}U}c5K=$TlgZM!4MMzw>SP`Yp6sDNIR=0b}ewW zum*;GDc%xx>#>GIHVYd83Wc@JWJnBTDVBC)B%3XnG$y>_tr?WwV@plWw93hUnyvQJ z!}d4jfmJnkHROSajYmv)c6N3QPPf3D35&%YdC;2{SE zSKn0@3Mr?RjYCNgxbbicp-@rla{1qcZg}cI4;!Pyi+r{u;WepR3MM5-FC{B&w(s$Q z$ZghdSuSs`Cl2P5Jg(^z(-@MWO}SuJ*%NoNRU5zQFxB#Un|V51CA=4P=(!Z-msTBr zCb*S*;Qu5I)d!Qp3SY6SE0zTO33wz}Oh zr5i2Syrxpb8MeCz@?0J_AOLY4*>Ta1)Hpn1FTy0tmL*@M-$>v(GQz^)3Y+T`D3-sG6#=WT1JHJKph7_nf{) zXuNd3`ug|&%~SkgcD0mQB5c`g=Y_ts32eS#f2w(G3uhAplT>A$ngz!L$q=wohYW#9 z;e$Y)P^S;+Q|9KA)B1pMEbTN!F3;)UG@PFb7u$cqOEqKdIdj}pZ#Kr=3izJ-I4|1Z zkZ>6hCFDZUuPFL}w0s10o;QXd;52kH`heu+fEF$tHI@MoQxXyqfEC@t&No3B7W>0+ zQHR+xm)jrwy$lM^G!SUj0^aYL2Di38{MO$lJ6K%*a>>9=5diEjDOdQsvzGiGY7!r! zJpX6fCY7bbOlmR--W*?u!nG;&1`%zoUewZsc6IJlUNo?A$|_=2)$?4WuS>in^xHw+ z8~TXu2WDDr2`mmp6E$6Qk@?>HdNqjKkX(gkX@@CQ}Ndl)+5|B#63Gh2u&}}7J zES`cfs0K$2^&$%S$XIF0N}dIcA}Uy+cr#8bR|a?bnnT}n9kWrP*g3Xk&7t{XAU%0* z)}K0U?HOzYYH&8>e$RO*T2~jOhJI^_q8@(F$>EiiL`t0jHvD2S<+P(Foidp<@O@46 zII#}DP!&VeRU$k!)}8nU;XRAcEB~=_gPTj|JMU_|2A*dg&8f#kitD6V=wILP6S{2G zs-PThv_R%nB@M{nZ2i9f_W~dd=fgpq^yTQ#TH$i?y@a#=kVxx?usVdPDD0(7H;C$a zxp;7T(Kj41H=ybx1P~beK zQb;voQOA*vJRcei0%0WPP5&2rKso@LNQ9JjkcHWh&oeWusu>7YwFDs*%3$Qg7bo2i zI8ZfmGsQlSO=?jskWzs?tmXb7xr&F6qlu8w&6#*IF6U2Q?poTLF>hqM@l>b^IvMxk zh+!+O|Gi69?ODDetHw*fo(?qqKbpQOEULC`d+2VE0fz375Rh&OLAtvI1PKA@ZWy|| z9=f|br9-+ILTN<0zUBKL{|0-ov$)r~&+9rXsWBDuIV5=zK{}yxm}WF0TCB@t~;ci}*UtG&ur=CX2zQIV@BrCffY_ zn&g0YW8KO}X+*2=yNz>7xq<#9a|CZSK9I~ST`G}%#gRDMwzj&!HnrzzOxBj(Z&%k_ zBXQDQ8FXM-DLUyBSFl3f6C#zrZR~g@y^-lT|5%woVsLEc5DfYr{gcENleox2``ePC z0wyQ)T$Qbkj8am#w8_!`Q-&j5|6GFk4qfl+t6Cg|Ds5pCnVSu`Y8FD;zpzxh(na;&1JAlZ!y95nl;(A0$J5lEBZ8C3x8?|mIf zx?%bBci=*C=D2UH;dP%UNxcudA8XC_Z#B)+O1l-k!FWEAe)4O6}vzuWO|}M zN+_E2@x^F!G6;cAd(sr$%iWPwRB-tm`1;Qe{-_|E6lz68)WT+TmukzR%D^vaHO=Mq zmm^786IcFgRPJ}1z?>-=X6Y2(Uc`ns zHQ0`${76BHbexNYS#9=MrH|P{GZMCYmJyvyk}YA3@PSVLxW}GaT77UhdSjeMf^eHC5bSNl92k*fdFL%tSUS0u?Dh6wG`j7rY>aD9)htn$J`z}uYu#M zN3P76a%Zu6IsAai*;*=tq5%=qv7ndpg0lehr5NTh-#T&aC&A?MEE;+@8Zn5xt_<+0 zNEC-7!w4Qq&`554dtWZ8x*GJmbEUy)zh60kxWd9^?pOtkpr-Ft1}FDox!R5cqL}z^|vP-UNDZaOV8y{Ztl4 z_|JMYCYT%n+|jUz9$Bw71}7aR@*-C>?w25bdQP=`wKp0iCRF%vXM&hq85?UkUy4lr z3;x#dRX<-)XbE5jijcN!V5^UaYAL0SGRed@7m_4$lVx@6UBb&`7Gte6#psJYHP<88 z9lkgz*D$Q%BbLQGAo;3CW&^uG^6vSRG&WE>-Cmx)q0Rpo8C`(fZY-gURe}1L$i|=6mFUNn~tFk_ML;dyl>F}6a|1eOvWHg@zi=3J?TnridNYI+xB#PBvV zd@VVrN%&D|9P&)Mx&*mASaZXPRc}_S-Y02UV`I^dzf;(vSya>fIFj!s@4{8nCHoWE zu%x|j^X}>_`r(fk{dX9~Vi#vK?cOgRX;n#*5MhoP2njr#gl_W2;U8sifTRFS4pB;I zn${3C%EmOy^#0F&>nr68+_6@TM8bdkyaEC8TDXDvEUcY9&j`XV%RtuXiWSgt0vFDM zkVj>BE6EyCH_HX#e`kFTES^)l|4{N;=IBdN;G(jdFiC9MnA;75yT7k#U%CO#D4n`* z^h}n3-YhSvV8yy%{%pHx$!LHUM=X%qxrLx`a&@}OX{WL-qLg_)mTypgw+nwUeEYUFLiLM4C!XAoX*!Y6UN8Ymht74S z5t0&G(x$*$c)uZ*5MewCq{#|YEzO0NfDDLEq$* z7v0?wZs4s(itBoCWx374cKqK8Sj33)75|TipimSY78|_3DN`gXGuSu7#9tf+UAkt< zU|P8nwphrKor(GxbyTW6j=8wMS2*7soAQ7UIb{l&x&Vw#TahkdrXa8iwZ1yBKr z#T!8nlq}~Y%ZSO$_d8;~59*zN{*0IYm%N8%rmQA4hR*$YqBq_gm;nyEmbc${zf>?q z`jL^7-Y?a&L2?cIa0BTSXLIa!x=z>X9JWM()DP3MthW4q)^SK6Bmeo+l@s8U=mQ5y z0oK5~2m%q$Gow&m#Rl=~pn2XFiWQ!1I5y4^egl7`BX^Zpr#aTFHLWrSda}Z=ntO3O zNvkHv=5>ghDN9jvgG9kq*6rf5Y8WY!bSY*sxP!WqG^P_I=y+h_uOaI76&hka7u8)3 z8G2KlYGXfGybd5};%yhCN){u#I2wDjXI4dqBO*Kef8Qj@NJ=wWE+m5Hf5P)&aba7R zbbL(IuPwH^QZ>T~vPsePGB-P~;w`EZZ)?TJEDu9AeCxs3ZuZ4RzL({ko(7Fj;8akd z+l>C#Q5UQ1co2chWjCl>lHw$qV{@~1lce#$PePmk85})jf$=eAbs&q*PDT6a&S9zGv)Jmu{G&Kbaiy!Jiow7W1fp^g>!Yv3aS`j4Dm1&;1;%I6-j{)(C| zbTE~oH16K4+JLzEFmzTn1|sD7gNhcD<)x>t`E|m1_4Ec?CLL*y-z0|%8R~4%ctYcS z-hIAp+p-ly!ab5@5_!9#|n6!-?_*zp&0R#vuw{GH}281}!8$ul1nHRAQD^ zNzGyM#x@mxUV-R#fcbCcz{8j3TsZlstodlwr>9iu#<4qJ9le~RkEC2CGsjKDns|=z z-9r>&Jz9e91CMU|w=zAplqb^}QrX8I1f%(n5e1nndsthKd`0Vex zG*jq9!$NBhig{as0LP1DBICZ%i`s^fWCz3c)BCg&7?8ZrL&h@jp<8Ps(-v_&SZ zxpIbddX_A&#hHvqZ5SF`gy?F>;IpnGpFjVF*1@gT`jTe-@zl%d^;xVpGMV+%G_PDG zg&u6lGzM8~aTr0s5%!n$y=1yM-@?d21%D;~*p$Et0)nT2HMd#ZUlgKOll!(F78Vc> zB9Bl{qBT!u>rIC3Mb~3@SVc_-GELo|?vMTPsBr9v*bsjIk{nO;SdklWv%{ACZ?1s> zTpM(L1%HmcjRJ(Tdux%21B%YrIPvmYkbzHct@e}3KoGX z>{pkDiQnZiWUUrUiW5yH=DmqEIl_iqIY=W!7Es5Vs|A@tIFMFFPw@zaw&QcTv2w`# zoZiInLY_lriX{=t$%DxCEv-!Jl5}7{%rJS4DCP3VW3TZRUOcwJblPBjr4bn!6$W>4 zNdE;kZCT6Ledje`ZCj1t=3X&NrU3=jiB#kG1gCG_e_am`qwqu}1C$2^qgBX(B{wWlm!tIoPiJ|%l$FfRufr-= z#zh*SIwn)&1;T7d$IVG!&PIod7SX{(c2xWho*QRvwS~F4dF$Prg5%=u5K|<)7w|g( z;Q+i3alE849bd70QC&N&C~=uX;LsLQZ}i^&_lR@t!u(~(Sm7~!YSb%c({aPyV z8LMR6FVCv_>?C|m=7EU}M)>GTILT6}K82EnY0u4?Lz%F0&&WNy6IqjWE7=Xp%$#HN z^WlJ5XvJz$l2-aO8n-ISszL*%WcZnZkpE=(tFav9+V&lAI78OSg4MwChN&Sgu2q2g z^Adi}71TI@sM8thc&=?a+b`YvsK3?!ub;)B>xk3}%?^jApG4~P?n3J6T=tdE_wp*N z?)tQ)GLb?VVzyN-&GME@(0q6fHWK@q8zd)IdWT}0ksLnAIo7vMyy7PZRhbaF!mQNo zLT=e|LaDwR`^H4iB_Mz{3_h6324Vt5AAZpaKb|!FGxpWFog0;)O;N3p+xp^7TB1<{ zzCh$d2+&S3?ff|O-AuSxO=5=)yOC>mD>DRyTFl%%CZ82j)q++E!>Ifq!LQbl={f#r7w! zNG$_2&!!K4VwGlH(tfc}XdrIn&EALB5+kY+?c`wHTm+B=-rM3*O-q5I)tiRXv`wPN z>XEC5J0lfFIa+*-BZ90oza?a8U7f?W@Pb2+{mFb&$Em>hM4X4_`Xu1FBdw5)k^h=! zL!#FrH5e!(A1ikg-Z>A^h@0XmpS7b>RBOC~O!5qjC9^smYdZ{;YgTYNY3(4)Hc(O19T}lcp!IcjC+x}YzxZN)&)q?)X-xcAlV@t%m(Kfxy$JPf zXuEuX9s&V6Ko^+~jS;mTlWh$~^BIK!UCdUQ8Rpj3s7Y!NK^N42ADf5kbo-7|264k7bMsWt<5E-E24wgj*R2FHaWEyi23*u`D4*^`*j-N{#LQILLf` zDw_8^C>$#0%^#sT#>{_8S~VDZJx$UgdF=g7Imq0A>a+5-GhfAgty%D2myh&HGuJ5& zmC;5YSEP59ABDUAR)gfDHoF>gTCA(ncT6)*L^ESV`VLRdAEUcD zHT~WovZQ|;W5u}{KJ4J@Ej#_`G3gt2UUnWWslfO!$o6JXfRtgKRMd40-s-JE@S1%O zd5h1ftxmHYNvNz$UXr9LA+FM|!+B*fpiV|KN|w?OGxuaULd$;A4LVnvgzQ8aHG--49CRI4{bO;jCz>bhg_i^4`0)5^O+>QPM$0P@c72C>dP8?Gksjo6bs!-h zQ79Yx&#VK)`RH`Ib4`gp{%d!mc4%=r`K7uCgbRh4%P5k?g@`Q;_|elalmA1Tp4CLXBFb@s%kpgEiG6sdbT>pYi7Ow+PYY2XZ>X}R z{*b4PG}11YCrx(x!CKzhvKL7;ZWXwQ;DcuN8#V}8psuP%_GN4Ba)S0<&s zrd8rJ9dC)%n--U3M_)Rij*R1S%Y9z@Yi%}*OZK^uP`J?5TFiN>>Jo>VvwfVngne{C z=UVhQ>+sx58(xR?>tqQ2+L0vCL<>Np-${>Iu;> zmrd+1N1HRqH(TV(iQLHQA0YysgqVbU>yETQrr#?zUyXj4bQJMgP(JrFFWV@wGj&g={b z@xxL=J}6qhg-2{SoEmmrG6?#&0{=&gam&a`Df}!?CHfcRSt2Ah`~a8^xsP*)>I!9n zmP@n4j^Mmx6s5Xz)$$XlGAT}J>Tn%>RAS2nEU z+%+=d`y0<^-@ndoQal9_lmyeBj~}-eD-8dVAPg=rmMp%V^g}jMT3-8EE+2Y}-_rJc z1srN)Uk7V=D+Gu;c&cvR25bU6%cNfZB5^Ywy=-g?RkIb3Ls$xsWus{8FpNaZj-Y@T zDIE5#cb8|p)@|Cp^JUfHa*sfHce16~%=tqQlA7(fP+}Vklf;Q5_n+9GoJkIK(vg~kFVn|MIGO8_0KT->* zS}uJ816_40Ys<67S`HNDAwldCWR-mcYz##dCs6DNa^}^Dn9XbHei-peam<(n{;a@e z|2Ftz`g8QeE=`tXX0C_&k%e>OPqPx?u}m&ppl3RXN`V_wz@$hcMep-^W^MbgpEm#L zlWAaWAnAwNo(7ITXfED}xMm-mz%Y-1=czb>Hg;$Gp6=Uk=i34Pi_F8n#n#0nfG`Qr*KPGj0Yb{99uKs~Tk_fffpJg~m0@kYW;(P+@hAuc-eXoI)1_$XUljBOT87#$CrlikJZ?iJQ$5UOSv(_YbKfCn z^s2g^KHDlP^;!q9YI!5sE>#a?@Y*`gh7e1l1}M#jCZH#wsmRniOjA4^6s6X^+#lAt z9&15_oYsAnVm$I$EGxW=YTajdizxm6Tuw3HjEv0yl+eUs`cWhTd+ zdJLzvrS8z0&2Jb}0&dI+JPk}X^6{uK1#ES0w-lXqmsp(-e^}kk2aq8^P;izir>qT4 zusPdIeZ@8_n9j8vb$dSqe=1E`AAug|-({XowfMz+k2lzVMyW1w77y!E z*hQ93R-49=4Zf(}XW=ImVI`S!TkWnMR}b*@c<@#0y7C@O=f)PW#k&bEmc=>)jB_?6 zAXPE)MFS`d;mwU3>{XALe3{VrId;DvHFCX}mvjrxgK; zQ!I+Nc>2vt5lT~-VeKp88UsluZyWKz&@Lk!E62PIt67NCj3{S& zMBn*&E(?XnX>Mv)NWVhCF}ExDGi?>F8UOcOA6Q<;467hO-)UH`T;1I{*XW-qG4^vW zlg*z;mnSe;lC<6hGWyMIs?b598ql;QSe ztjw|S0>ZqI!^N5rn6hZVZSz+tMh@WUf8_wpaNh$ocmuB9L&WBWC{~(&rrh=nA zct3B#_g;M}Ut-q2r59<$GSw(le`y2S#8)*mlxhH_v!!xy>rKl(RVd;V5C{Nl)@0LS zx57rA_m(FsT_~S89T~?88j+K-dDLV%{_2Od9Vw7ty(J3I3>kjA@_T)4*B_!jE~k+` zyv^XCzAEiifh!zPwqS_cT&CKw8@Vjse?&p0lZESz7%Q+~L_gJ)mMHZ(f9wivOgmpR zLT&lR<7xB3qs*)OJ*LqSx-lYD~_OgTvinXkAio0TT$_ zLQ0DNw$r)p`=p|d&phcwrWmC;_i)^yKq(jJ&x{~fy{~rbjcBnie^UQV22Ou}aiQGM zGmYc_#BJS(46(`yAgA;b9wiSN6w`UlKCWz-diQvHiU8DXy=*WZGf7HGDOTz@(Vx8> z@Hw6~Et%~U4B@V8>6WX3=&e7K#6UzMwf(Npjok0)?N;iMgxtIlzcAH*e&fCw{y9;U z6R2|rJRiB~cy@+;vMqvn174mN=(8?iDMU}im;JR{7+_ff3)qS$ zN{hau)oG1B=yu8utp%5qj7~+;1>mAJCiE4Gb`w9d*nxuzSn^m%=)QJ=Kdra7Fo<=% zJ-%!BH2)JFNg&BbdmWgRcf0bFTyE!^=U$V#cG6MG)o=r0PnL(K*NS}RldGAIv-KEU z!tV#ZOGo1CX3!|&C&`;lS8uoPOeZ`%tBGjau#oKl1dTjE5Q7L?K zz`c#A5+%MSDks*D2(c=!Z%kGbhtAtrZL25#)Cl9P394?&q0t~{=`&wlb8%^Rr~4*o zeCLUhcc!p)?$8Osgb8b0YoTi?=64N!{1SO$_u=&jsaDmhGl*iS_0DMU^ZU9B<(|U| z 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 literal 0 HcmV?d00001 diff --git a/config/REPO/config.ini b/config/REPO/config.ini new file mode 100644 index 0000000..b21746c --- /dev/null +++ b/config/REPO/config.ini @@ -0,0 +1 @@ +seed=https://arch.myddns.me/app/lunch/?repo \ No newline at end of file diff --git a/config/REPO/icon.png b/config/REPO/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e519ca1e5ed2f619bb00f66b36bbc92eda5a04 GIT binary patch literal 99697 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