ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- Encodings/iso-8859-2.enc000044400000002060152344545640010520 0ustar00ISO-8859-2  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A=Z`^dy}{B>[a_ez~|T9 CGPXnpbU: DHQYoqcEncodings/iso-8859-8.enc000044400000002060152344545640010526 0ustar00ISO-8859-8  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ > Encodings/x-euc-jp-jisx0221.enc000044400000112002152344545640012062 0ustar00X-EUC-JP-JISX02214A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~g?gL?^^PCKSVL8Q +^K^^^e^^!^^^;^^^U^^^o^^ +^ ^ ^ E^ ^ ^ _^ ^ ^ y^ ^ 5^ ^ ^O3^^>^^^X^^^r^^.^^^H^^^b^^^|^^8^^^R^^^l^^(^^^B^^^\^~Ca=}0VWWA^^^T^^^n^^ *^ ^ ^!D^!^"^"^^"^#^#x^#^$4^$^$^%N^%^& ^&h^&^'$^'^'^(>^(^(^)X^)^*^*r^*^+.^+^+^,H^,^-^-b^-^.^.|^.^/8^/^/^0R^0^1^1l^1^2(^2^2^3B^3C3  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOabcdefghijklmnopqrstuvwxyz{|}~PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~000 000@>?00000N0000  \0 \ & %     00;=[]00 0 0 0 0 0000 ""`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%BNUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{QĐyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQq~!"!    RSTUVWXYZ[\^_&2A?JRf'138B@IKSg  " $0*.(469=;CGEPLTXVZ\`^dblpjrnhtxvy}{   !%+/)57:><DHFQMUYW[]a_ecmqksoiuwz~|NNNN NNN#N$N(N+N.N/N0N5N@NANDNGNQNZN\NcNhNiNtNuNyNNNNNNNNNNNNNNNNNNNNNNOOOOO O OOOOOO.O1O`O3O5O7O9O;O>O@OBOHOIOKOLOROTOVOXO_OcOjOlOnOqOwOxOyOzO}O~OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPP P PPPPPPPPPP"P'P.P0P2P3P5P@PAPBPEPFPJPLPNPQPRPSPWPYP_P`PbPcPfPgPjPmPpPqP;PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQ Q Q QPQQQQQQQQ#Q'Q(Q,Q-Q/Q1Q3Q4Q5Q8Q9QBQJQOQSQUQWQXQ_QdQfQ~QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRR"R(R1R2R5RSBSLSKSYS[SaScSeSlSmSrSyS~SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTT!T'T(T*T/T1T4T5TCTDTGTMTOT^TbTdTfTgTiTkTmTnTtTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUUU U U UUU*U+U2U5U6U;UW?WEWFWLWMWRWbWeWgWhWkWmWnWoWpWqWsWtWuWwWyWzW{W|W~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXX WX X XXXX X&X'X-X2X9X?XIXLXMXOXPXUX_XaXdXgXhXxX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYY Y YYYAYY!Y#Y$Y(Y/Y0Y3Y5Y6Y?YCYFYRYSYYY[Y]Y^Y_YaYcYkYmYoYrYuYvYyY{Y|YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZ Z ZZZZZ#Z$Z'Z(Z*Z-Z0ZDZEZGZHZLZPZUZ^ZcZeZgZmZwZzZ{Z~ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[4[[[[![%[-[8[A[K[L[R[V[^[h[n[o[|[}[~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\ \\\\#\&\)\+\,\.\0\2\5\6\Y\Z\\\b\c\g\h\i\m\p\t\u\z\{\|\}\\\\\\\\\\\\\\\\\\\\\\\\\]]] ]]+]#]$]&]']1]4]9]=]?]B]C]F]H]U]Q]Y]J]_]`]a]b]d]j]m]p]y]z]~]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^ ^^^^^^ ^.^(^2^5^>^K^P^I^Q^V^X^[^\^^^h^j^k^l^m^n^p^^^^^^^^^^^^^^^^^^^^^^^^^^_________!_"_#_$_(_+_,_._0_4_6_;_=_?_@_D_E_G_M_P_T_X_[_`_c_d_g_o_r_t_u_x_z_}_~________________________________________`` ` ```````$`-`3`5`@`G`H`I`L`Q`T`V`W`]`a`g`q`~``````````````````````````````````````````aaa a aaaaaaaaaaa"a*a+a0a1a5a6a7a9aAaEaFaIa^a`alaraxa{a|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbb b"b#b'b)b+b9b=bBbCbDbFbLbPbQbRbTbVbZb\bdbmbobsbzb}bbbbbbbbbbbbbbbbbbbbbbccc c c ccccc)c*c-c5c6c9cgEgGgHgLgTgUg]gfglgngtgvg{gggggggggggggggggggggggggggggggggghRhhhhh(h'h,h-h/h0h1h3h;h?hDhEhJhLhUhWhXh[hkhnhohphqhrhuhyhzh{h|hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhii i iiiiii1i3i5i8i;iBiEiIiNiWi[icidieifihiiilipiqirizi{iiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjj j$j(j0j2j4j7j;j>j?jEjFjIjJjNjPjQjRjUjVj[jdjgjjjqjsj~jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkk kkkkkkk$k(k+k,k/k5k6k;k?kFkJkMkRkVkXk]k`kgkkknkpkuk}k~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllll l llllll&l'l(l,l.l3l5l6l:l;l?lJlKlMlOlRlTlYl[l\lklmloltlvlxlyl{llllllllllllllllllllllllllllllllmmm mmmmmm&m'm(lgm.m/m1m9mu?u@uCuGuHuNuPuRuWu^u_uauouquyuzu{u|u}u~uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvvvvv v vvvvvvvvvvv#v%v&v)v-v2v3v5v8v9v:vwBwEwFwJwMwNwOwRwVwWw\w^w_w`wbwdwgwjwlwpwrwswtwzw}wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxx x xxxx!x"x#x-x.x0x5x7xCxDxGxHxLxNxRx\x^x`xaxcxdxhxjxnxzx~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyxxxxxyy yyyyyy y%y'y)y-y1y4y5y;y=y?yDyEyFyJyKyOyQyTyXy[y\ygyiykyryyy{y|y~yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyzzzz z z zzzzz!z'z+z-z/z0z4z5z8z9z:zDzEzGzHzLzUzVzYz\z]z_z`zezgzjzmzuzxz~zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{{#{'{){*{+{-{.{/{0{1{4{={?{@{A{G{N{U{`{d{f{i{j{m{o{r{s{w{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{|||||| | | ||||| |%|&|(|,|1|3|4|6|9|:|F|J|U|Q|R|S|Y|Z|[|\|]|^|a|c|g|i|m|n|p|r|y|||}|||||||||||||||||||||||||||||||}}}} }}}}}}}}#}&}*}-}1}<}=}>}@}A}G}H}M}Q}S}W}Y}Z}\}]}e}g}j}p}x}z}{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}~}}}}}}}}}}}~~~~~~~~ ~'~(~,~-~/~3~6~?~D~E~G~N~P~R~X~_~a~b~e~k~n~o~s~x~~~~~~~~~~~~~<;=>?CDGORS[\]acdefmq}~  $&,.04579:<>@D`dfmquȀ̀πҀԀՀ׀؀  $',05:@CEMX]adeoqr{ȇɇʇ·Շևهڇ܇߇ (-.025:@BEFIORWZ[\abcknpsuz{|}ԉՉ։׉؉ "$&+,/57=>@CEGIMNSVWX\]aeguvwyz{~ÊƊȊɊʊъӊԊՊ׊݊ߊ  -07EGIKOQSTWX[]Ycdfhimsuv{~ŌƌɌˌό֌Ռٌ݌ eilnōƍǍȍʍ΍эԍՍ׍ٍ  !"#&'136789=@AKMNOT[\]^abilmopqyz{ÎĎǎώюԎ܎ !#%'(,-.4567:@ACGOQRSTUX]^eƏʏˏ͏ЏҏӏՏ ()/*,-347?CDL[]bfglpty̐ÐĐŐǐȐՐאِؐܐݐߐҐ  %"#')./14679:<=CGHOSWYZ[adgmtyz{‘Ñőӑԑבّڑޑ #$%&(./035689:<>@BCFGJMNOQXY\]`aeghinopuvwxy{|}’ÒŒƒǒȒ˒̒͒ΒВӒՒגْؒܒݒߒ !$%')*3467GHIPQRUWXZ^degijmopqstvz}ēœƓǓɓʓ˓͓̓ӓٓܓޓߓ ./1234;?=CEHJLUY\_achkmnoqrxy~ƕȕɕ˕Еѕҕӕٕڕݕޕߕ"$%&,13789:<=ARTVWXant{|~ʖ]ؖږݖޖߖ !"#(13ACJNOUWXZ[cgjnsvwx{}ėŗǗɗʗ̗͗ΗЗїԗחؗٗݗޗۗ   #&+./0235%>DGJQRSVWYZbcefjl˜ŘȘ̘"&'+123459:;<@AFGHMNTXY[\^_`Ùəәԙٙڙܙޙ  "#$'-.3568GADJKLNQTV]ÚƚȚΚКҚ՚֚ךۚܚ  &+-34579:=HKLUVW[^acefhjklmnsuwxyǛțΛЛכ؛ݛߛ "#&'()*1567=ACDEIJNOPSTVX[]^_cij\khnpruw{ /0234:?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO!QRSTUVWXYZ[\^_Encodings/euc-kr.enc000044400000131352152344545640010351 0ustar00EUC-KR}F  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}?A}A;AAAuA3AAAmA+AAA eA #A A A ]A A AAUAAAAMA AAAEAAAA=A?AA^AAAxA'_AAAVA A` A`!A`!}A!A"A#YA$A$A%A&QA'A'A(A)IA*A*A+A,AA,A-A.{A/9A/A0A1sA21^2^3M^3^4 ^4g^4^5#^5^5^6=^6^6^7W^7^8^8q^8^9-^9^9^:G^:^;^;a^;^<^<{^<^=7^=^=^>Q^>^? ^?k^?^@'^@^@^AA^A^A^B[^B^C^Cu^C^D1^D^D^EK^E^F^Fe  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| !"#%&'()*+.234567:;=>?ABCDEFGHIJLNOPQRSUVWYZ[]^_`abcdefghijklmnorsuvy{|}~¬ìŬƬǬɬʬˬͬάϬЬѬҬӬԬ֬ج٬ڬ۬ܬݬެ߬ !"#$%&'(*+./0123679:;=>?@ABCFHJKLMNOQRSUVWYZ[\]^_`bdefghijknoqrwxyz~­íŭƭǭɭʭ˭̭ͭέϭҭԭխ֭׭ح٭ڭۭݭޭ߭  !"#$%&'()*+,-./23569;<=>?BDGHIKOQRSUWXYZ[^bcdfgjkmnoqrstuvwz~®îŮƮǮȮɮʮˮήҮӮԮծ֮׮ڮۮݮޮ߮  !"#$%&'()*+./1356789:;>@DEFGJKLMNOQRSTUVWXYZ[^_`abcfghijklmnopqrstuvwxz{|}~¯ïįůƯʯ̯ϯЯѯүӯկ֯ׯدٯگۯݯޯ߯  !"#$%&')*+,-./0123456789:;<=>?@ABCFGIKMOPQRVXZ[\^_`abcdefghijklmnopqrstuvwxyz{~°ðưʰ˰̰ͰΰϰӰհְװٰڰ۰ܰݰް߰  !"&')*+-./01236:;<=>?BCEFGIJKLMNORSVWYZ[]^_abcdefghijklmnopqrstuvwz{}~±ñıűƱDZȱɱʱ˱ͱαϱѱұӱֱױرٱڱ۱ޱ !"#$%&'()*+,-./012356789:;=>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]^_abcdefgjklmnopqrsvwxyz{}~²òIJŲƲDzʲ˲ͲβϲѲӲԲղֲײڲܲ޲߲  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSWYZ]`abcfhjlmorsuvwyz{|}~³óƳdzɳʳͳϳѳҳӳֳسڳܳ޳߳ !"#$%&'*,-./012356789:;<=>?@ABCDEFGHIJKLMNORSUVWYZ[\]^_bdfghijkmnopqrstuvwxyz{|}~´ôŴƴǴɴʴ˴̴ʹδϴѴҴӴԴִ״شٴڴ۴޴ߴ  !"#&+,-./235679:;<=>?BFGHIJNOQRSUVWXYZ[^bcdefghijklmnopqrstuvwxyz{|}~µõŵƵǵȵɵʵ˵εҵӵԵյֵ׵ٵڵ۵ܵݵ޵ߵ  !"#$&'()*+-./012356789:;<=>?@ABCDEFGIJKLMNOPQRSTUVWXYZ[\]^_`abcefgijklmnopqrstuvwxyz{|}~¶öĶŶƶǶȶɶʶ˶̶Ͷζ϶жѶҶӶնֶ׶ضٶڶ۶ܶ޶߶  !"#$%&'*+-.1234567:<=>?@ABCEFGIJKMNOPQRSVWXYZ[\]^_abcefgijklmnortvwxyz{~·÷ķŷƷȷʷ˷̷ͷηϷзѷҷӷԷշַ׷طٷڷ۷ܷ޷߷  !"#&')*+-./01236:;<=>?ABCEFGHIJKLMNOPRTUVWXYZ[^_abcefghijknprstuvwyz{}~¸ĸƸǸȸɸʸ˸͸θϸѸҸӸոָ׸ظٸڸ۸ܸ޸ !"#$%&'()*+,-./0123456789:;>?ABCEFGHIJKMNPRSTUVWZ[]^_abcdefgjlnopqrsvwyz{}~¹ùĹŹƹǹʹ˹͹ӹԹչֹ׹ڹܹ߹  !"#$%&'()*+,-./01234567:;=>?ACDEFGJLOPQRVWYZ[]^_`abcfjklmnorsuvwyz{|}~ºúźƺǺɺʺ˺̺ͺκϺкѺҺӺԺպֺ׺ںۺܺݺ޺ߺ !"#$%&'(*,-./012379:?@ABCFHJKLNQRSUVWYZ[\]^_`bdefghijkmnopqrstuvwxyz{|}~»ûŻƻǻɻʻ˻̻ͻλϻѻһԻջֻ׻ػٻڻۻܻݻ޻߻  !"#&(*+,./235679:;<=>?BFGHJKNOQRSTUVWXYZ[\^_`abcdefghijklmnopqrstuvwxyz{|}~¼üżƼǼȼɼʼ˼̼μҼӼԼּ׼ټڼۼݼ޼߼  !"#%&'()*+-./0123456789:;<=>?ABCDEFGJKMNOQRSTUVWZ[\]^_`abcefgijklmnopqrstuvwxyz{|}~½ýĽŽƽǽȽɽʽ˽̽ͽνϽнѽҽӽֽ׽ٽڽ۽ݽ޽߽  !"#$%&'()*+,-./0123456789:;<=>?@ABCFGIJKMOPQRSVX\]^_bcefgiklmnorvwxyz~¾þľžƾǾȾɾʾ˾̾;ξϾҾվ־پھ۾ܾݾ޾߾  !"#$%&'()*+,-./0123456789:;<=>?BCEFGIJKLMNORSTVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¿ÿĿƿǿȿɿʿ˿οϿѿҿӿտֿ׿ؿٿڿۿݿ޿  !"#$%&'()*+,-./0123456789:;=>?@ABCDEFGHIJKLMNOPRSTUVWYZ[]^_abcdefgjklmnopqrstuvwxyz{|}~ !"%()*+.23457:;=>?ABCDEFGJNOPQRSVWYZ[]^_`abcfjklmnoqrsuvwyz{|}~ !"#$%&'*,.0356789:;<=>?@ABCDEFGIJKLMNORSUVWYZ[\]^_abcdfghijknoqrsuvwxyz{~€‚ƒ„…†‡Š‹ŒŽ‘’“”•–—™šœžŸ ¡¢£¦§©ª«®¯°±²³¶¸º»¼½¾¿  !"#&'*+,-./0123456789:;<=>?@ABCDFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgjkmnoqstuvwz{~ÀÁÂÃÅÆÇÉÊËÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ  !"#%&'()*+-./12356789:;>?@ABCDEFGIJKLMNOPQRSTUVWXYZ[\]^_`abcfgijkmnopqrsvwxz{|}~āĂ㥹ĆćĈĉĊċČčĎďĐđĒēĕĖėĘęĚěĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĹĺĻĽľĿ  !"#$%&'*+-./1234567:<>?@ABCFGKOPQRVZ[\_bcefgijklmnorvwxyz{~ŁłŃŅņňʼnŊŋŎŐŒœŔŖřŚśŝŞşšŢţŤťŦŧŨŪūŬŭŮůŰűŲųŶŷźſ  !"#&')*+/1268:<=>?BCEFGIJKLMNORVWXYZ[^_abcdefghijkmnprstuvwz{}~ƁƂƃƄƅƆƇƊƌƎƏƐƑƒƓƖƗƙƚƛƝƞƟƠơƢƣƦƨƪƫƬƭƮƯƲƳƵƶƷƻƼƽƾƿ "#%&')*+,-./24689:;>?ABCEFGHIKNPYZ[]^_abcdefgijlmnopqrsvwyz{ǀǁǂdžNjnjǍǏǒǓǕǙǛǜǝǞǟǢǧǨǩǪǫǮǯDZDzdzǵǶǷǸǹǺǻǾ !"#%&'()*+.02345679:;=>?ABCDEFGJKNOPQRSUVWXYZ[\]^_`abcdefghijklmnorsuvwy{|}~ȂȄȈȉȊȎȏȐȑȒȓȕȖȗȘșȚțȜȞȠȢȣȤȥȦȧȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȾȿ 000 % &0 "%<"<    0000 0 0 0 0 0000"`"d"e""4 2 3!!+&B&@" "#"""a"R ;&&%%%%%%%%%%%!!!!!0"j"k""=""5"+","" """""*")"'"( !"#$%&'()*+-./012356789:;<=>?@ABCDEFGHIJKLMNORSUVWYZ[\]^_bdefghijkmno!!""^".""! 0%%%%&d&`&a&e&g&c"%%%%%%%%%%%&h&&&& !!!!!!&m&i&j&l22!3!"33!!qrsuvwxyz{}~ɀɁɂɃɄɅɆɇɊɋɍɎɏɑɒɓɔɕɖɗɚɜɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿ  !"#$%&'()*+,-./0123456789:;=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]  !"#$%&'(*+,-./0123456789:;<=>?@ABCDEF1112131415161718191:1;1<1=1>1?1@1A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V1W1X1Y1Z1[1\1]1^1_1`1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1r1s1t1u1v1w1x1y1z1{1|1}1~1111111111111111GHIJKNOQRSUVWXYZ[^bcdefgijklmnopqrstuvwxyz{|~ʀʁʂʃʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧ!p!q!r!s!t!u!v!w!x!y!`!a!b!c!d!e!f!g!h!iʨʩʪʫʬʭʮʯʰʱʲʳʴʵʶʷʸʹʺʻʾʿ %%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%B%%%%%%%% %%%!%"%&%'%)%*%-%.%1%2%5%6%9%:%=%>%@%A%C%D%E%F%G%H%I%J "#$%&'()*+,-./0123456789:;<=>?@BCDEFGJKMNOQRSTUVWZ[\^_`abcefghijkl333!3333333333333333333333333333333333333333333333333333!&3333333333333333333333mnopqrstuvwz{|}~ˀˁ˂˃˄˅ˆˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˝˞˟ˠˡˢˣˤ˥˦˧˨˩˪˫ˬ˭ˮ˯˰˱˲˳˴˵˶˷˹˺˻˼˽˾˿&2?ARfJ2`2a2b2c2d2e2f2g2h2i2j2k2l2m2n2o2p2q2r2s2t2u2v2w2x2y2z2{$$$$$$$$$$$$$$$$$$$$$$$$$$$`$a$b$c$d$e$f$g$h$i$j$k$l$m$n!S!T![!\!]!^  #$'138@BSgKI2222222222 2 2 2 2 22222222222222$$$$$$$$$$$$$$$$$$$$$$$$$$$t$u$v$w$x$y$z${$|$}$~$$$$ t  %&*+-/1234567:?@ABCFGIJKMNOPQRSVZ[\]^_abcegijklmnoqrstvwxyz{|}~̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~000000000000000000000̶̷̡̢̧̛̖̗̝̞̟̣̤̥̦̪̮̯̰̱̲̳̹̺̻̔̽̾̿̕̚00000000000000000000000000000000000000000000000000000000000000000000000000000000000000  !"#%&')*+-./012345678:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_ !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNOabcefghijknprstuvwyz{|}~͇͉͍͎̀́͂̓̈́͆͊͋͌ͅ͏͓͖͙͚͐͑͒͗͛ͣͦͨͪͫͬͭͮͯ͟͢͝͞͠͡ͱͲͳʹ͵Ͷͷ͸͹ͺͻͼͽ;Ϳ "#%&')*+,-./246789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWZ[]^bcdefgjlnopqrsvwyz{}~΀΁΂΃ΆΈΊ΋Ό΍ΎΏΒΓΕΖΗΙΚΛΜΝΞΟ΢ΦΧΨΩΪΫήίΰαβγδεζηθικλμνξο  $,-/0189<@KMTX\pqtwxzĬȬ̬լ׬ !"#%&'()*+.2345679:;<=>?@ABCDEFGHIJKLMNOPQRSVWYZ[]^_`abcfhjkl  ),-458?@ABCFHJKLMNOQRSUVWYZ[\]^_abcdefghijknoqrsuvwxyz{~ЀЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГД߱  4?BFGHIJKNOQRSUVWXYZ[^`bcdefgijkm@ACDEKLMPT\]_`aĵ̵͵ϵеѵص%,4HdhԶ(),/089;DHLTU`dhpqsu|}nopqrstuvwxyz{}~рстухцчщъыьэюяѐёђѓєѕіїјљњћќѝўџѢѣѥѦѧѩѪѫѬѭѮѯѲѴѶѷѸѹѻѽѾѿϷǷɷ $%(,45789@DQS\]`dlmoqx|øŸ̸иԸݸ߸ <=@DLOQXY\`hi  !"#$%&'()kmtux|ȹɹ̹ιϹйѹҹعٹ۹ݹ޹89<@BHIKMNSTUX\deghipqtxĺȺغٺ*+./12356789:;>@BCDEFGIJKLMNOPQRSTUVWXYZ[]^_`abcefghijklmnopqrstuvwxyz{|}~҂҃҅҆҇҉ҊҋҌ  )+4568;<=>DEGIMOPTXaclĻȻлӻ $%')-0148@ACDEILMP]ҍҎҏҒғҔҖҗҘҙҚқҝҞҟҡҢңҥҦҧҨҩҪҫҭҮүҰҲҳҴҵҶҷҺһҽҾļͼϼмѼռؼܼ $,@HILPXYdhԽսؽܽ DEHLNTUWYZ[`ad "#$&'*+-./1234567:>?@ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghihjpqstu{|}оѾԾ׾ؾ @ADHPQUſ̿ͿпԿܿ߿?ABCEFGHIJKLMNOPQRSTUVWXYZ[]^_abcefghijklnpqrstuvwz{}~ԁԃԄԅԆԇԊԌԎԏԐԑԒԓԕԖԗԘԙԚԛԜԝ4<=HdehltuyĀĔĜĸļ (),089;=DEHIJLMNSTUWXY]^`adhpqstu|}ŀńŇŌōŏőŕŗŘŜŠũŴŵŸŹŻżŽžԞԟԠԡԢԣԤԥԦԧԨԪԫԬԭԮԯ԰ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿ $%(,-.034579;@ADHPQSTU\]`loqxy|ƀƈƉƋƍƔƕƘƜƤƥƧƩưƱƴƸƹƺ  !"#$%&'()*+,-./0123456789:;>?ABCEFGHIJKNPRSTUVWZ[]^_abc  !$(01357<=@DJLMOQRSTUVWX\`hktux|}~ǃDŽDžLJLjljNJǎǐǑǔǖǗǘǚǠǡǣǤǥǦǬǭǰǴǼǽǿ dfgjlnopqrsvwyz{}~ՀՁՂՃՆՊՋՌՍՎՏՑՒՓՔՕՖ՗՘ՙ՚՛՜՝՞՟ՠաբգդզէըթժիլխծկհձղճմյնշոչպջռսվտ $,-/18<@HILMTpqtxzȀȁȃȅȆȇȋȌȍȔȝȟȡȨȼȽ ,4PQTX`aclpt|ɈɉɌɐɘəɛɝ !"#%&'()*+,./01234567:; )LMPT\]_`ah}ʄʘʼʽ !AHILPXY]dxy˜˸ !"'(),.089;=>?ABCDFGJLNOPRSVWYZ[]^_`abcdefhjklmnorsuvwxyz{|}~րցւքֆևֈ։֊֋֎֏֑֖֛֢֣֤֥֦֧֪֚֒֓֕֗֘֙֜֞֠֩<=>DEHLTUWXY`dfhpų̴̵̸̘̙̜̠̩̫̬̭̼ $(,9\`dlmoqx͈͔͕ͤͥͧͩ͘͜Ͱ  !$(0135ֱֲֳִֵֶַָֺּֽ֭֮֫֯־ֿ XY\_`ahikmtux|΄΅·ΉΐΑΔΘΠΡΣΤΥάέ $,-/018TUX\degipqtxπυόϡϨϰ-458<!"#$%&'*,./0123679:;=>?@ABCEFHJKLMNORSUZ[\]^_bdfghjkmnoqrsuvwxyz{~׀ׂ׃ׅׄ׆ׇ׊׋DEGIPTX`lmpt|}ЁФХШЬдезй 0148:@ACDELMPT\]_ahl|фшѠѡѤѨѰѱѳѵѺѼ ,-04<=?AH\׍׎׏בגדהוזחךלמןנסעףdҀҁ҄҈ҐґҕҜҠҤҬұҸҹҼҿ  !%(),089;<=DE|}ӀӄӌӍӏӐӑӘәӜӠӨөӫӭӴӸӼ@D\`dmoxy|ԀԂԈԉԋԍԔԩ <=@DLMOQXY\`ehikmtux|ՄՅՇՈՉՐե $-89<@EHIKMQTUX\gipqtփօ֌֍֐ְֹֻ֔֝֟֡֨֬ ()+-458ahe9iouvv{U[WQ|P(S\E]bcnddn py[ݎ}EN~NPe]^aiWqTGu+N^Pgph@Q RRjwR`/PHacdhpLt/t{Pʼnܙ(R.`]bOQIS!X^fm8prs{P[SfckNVPXJX`*a'biЛA[}_NPTU[ ]]e*eNh!jKrvw}^NߏNʙUNNEN]NOQwRS@SSTVWuW[]^abeQggikPkklBnpxrstwwzv}  ߈b3dҚEןW \@ʗTzَ͐X\Hcz[_zyzP&R8RSwWbcrk mw7SsWhvg:jopm̙Kfwkx<SW-YNcisxEzz|us5RWGuG{`̒jXQKRKRbhiuPRRaeh9it~{K뉲9љI NYdfjt4yy~_ &O S`%bqlr}}fNQbw܀OOQvQUVhW;WWYYGY[\]]^~_beeggg^hhj_k:l#l}lmst&t*ttuxuxxyAyGyHyz{}}-OHw!$Qe}OvT bhTUQ: Za bbfqV cOczSW!gi`ns"u7#$%} &'rVZ()*+,NC-QgYHg.Ys^tdy_`lbc{[[R/Yt_)`012tY3456789:;<=>?@ABCoDE`FGfHI\?JKLMNOPQZ%g{}RSTUVWXY\r-RL]Pde,ko|C~͉dbɁ؈^gmjrttoO] _ QcueNPQiQhj|||oҏOQ7RTB^anb>ejoy*܈#bjRfkwpy+bBabe#o#qIt}o&#JQRRm pȈ^eko|>suNO6V_\]`s{-΀F4HaOoyR`ddjo^prv\2ouxy}ɓX_g'p't|`~Q!p(rbxʌŒڌNP[^eqvBwJ|'XZA\bjmov;}/~78KRegimAnpt t`uYv$xk,^Qmb.xOP+]m}*_aDhaRҀQQi^z}uOR)STU\e`gNhmlrrttbu|lyψ̑ЖTo~qtWgmt3x,z{ |ditjuxx虬T[^Uo NSMZ)]_Nabc=fifno+pcw,;E;Ubg+l jzNY__g}T+WYZ[f'ghkqdu㐁EL@[_lsvv߄ QQMQRhlww }}bnŅQT T}ffi'nvw‡iOQRY^=aUdxdyfgj!kkr_ratAw8wۀ(g(lrgvwfzFklY"g&SoXY^cf4gsn:s+zׂד(R]aab bdeiYkfkq!su]~Fj'aXPRT;UOelv} } ^RlriTsZ\>]K_L_g*hicneef ginx}!+*2P OcW_bcgonCqvÀ̀ڈ)MjO/Op^gh"v}v~D^aj qiqujd~ACO{OpQ^hl>lNlr{ălt:PRXdjtvVx9eS^_R%wINPQu\[^wff:ghpuuyzݏ' OX!X1[fnkemnzo}su+܉\OPSS\[_g yy/9;g,NvOYI\\\cghpqt+~+"ҜN NOPRVRoT&TWY+Zf[Z[u[^fbvewemnnr6{&|?6PQ@tܖDٜSRT)VtXYTYn_abnfl~qv||}gO[__b])g hx|~ClNPSS*SQYZb^`abIbyegikkkklht5uxxyy|}ဥ>ƒ芹l^۟;V[*_lejkm\opr]sӘ;al7XNMNNNO:Oy@y`y{}}r цLjߊP^܍fߞRJigjPR*\qeclUsu#u{x0Nwdkq^N kgIhnkcoN PPQUFUV[@\\^8^^^`hQjanXr=r@rvye{ԈsaޗX^tUlza}"rrruu%m{XX]^^_`UbceMfffhhrt^{n}n}r͟ YYm^-`ffsglPmo_wxƑ˓+NPQHU[ [bGe~en2q}ttDttvly}~Uz9ux%MSh\QiTlm)n+ ;-gRafk~ ]emqnWY[`'`bff_s)svw{lVreNRkrmz{9}0oSV/XQ[\\]b@cdf-hlmnppqu&uuv{{|+} }9,m4 a7O\lg_m|~[k]d \s[`g~mފ R7ppQxpOSUVWXZ[\\^%ab bKcde6exj9kl4mo1qrsxttv&wayzWz|}}~a)1څꈖ8Bl֗ӛSX~Y[p[moZqt!t]__`BehiojSkm5msvw{M}#@cbđb Se]]']it_hob҉6rNNXPRSGbf~i^OSV6YZ\8\N\M^_`Cef/fBggswy:ń͉fiUzW[_`obi kn\q{҇UXߘO8OOT{Z [aT3UXbXYgZ[`aeVefdhlZopqsR{}2\KlsDs:ntevzi~ Q@Xdtuvp͙Tn&tzzهxZI[[himcstt,x}UL.f_egljsP-ZkjwY]l]s%uOPQX/Y-YY[]bdddfjHqtdzz~G~^p‡ YÐRa~k2mt~%OPQRWX[^aBimngnqtbu(u,s8Ɏ NOQPvQ*SSS[[\$aaer[st@vyPyy}Ն^GꖅR_gef1h/q\z6 NjRkoqSK1NqQCSTWWWZZ[`(a?clm9nrnr0s?tWшE`ƖbXg^OMPIPSqW YZ\ apfn-r2tK}Äf?_[U˛ONsOQQjU/U[z[^|^}^``aa ce8g ggiaiblm'n8os6s7t\u1vR}8Պۊ0BJ>zIɓnX kӀQAYk\9odsגۀbp}hW`iaGkNYTm-pcl㐑QaɁOPQ[aadikuwdcpNNO Y7Y]__[`!r>supuy 3Q茽 p7vNNRSpTVY[__nn}j5mwNOZO~Xen8NXYY`AzOQeSDNRi[UNR:TYY[P[W[\`caHnpqnstux}+(ɊǖO\RVef(p|pr5}Lr[qhkozv\fo[{|*6NNS X4XXYl\^3^_5cfgVjjk o?rFsPtz|x߁烊l#ψݍwQTW([bMgPh=hn=np}~! KNr-{͓OGONQ2TY^bguinjlnrs*u{}5W[Ο_RT Z[dXeunrvzM{|M~>߃{+ʍd_iOCOzPQhQxRMRjXaX|Y`\\U^`b0hkloqNt u0u8uQvr{L{{{~n>I?"+ZkRb*bmYvdz{}vS`\^o8p|cdzvNNNP\PuTHY[^@^^_`c:e?etefvfxgihjkcl@mmnn^ppssu:w[xyz z}|}Gꌞ-Jؒf̓ V\R6RU|X$^_`choym{,ͅDd=LJOQFQRV2__kcdefAffghhioonqgqr*tw:yVyZyz z||}D~pT m;՜e|[X\ SRbsP'[_`akhmt.z.}B}~1k*5~OPWP]^c+jN;OOOPZY݀TjThUYO[]^f]g1gh*lm2nJopsu|L}},}ۊ;p31NRDz|OQQW[\fYj=mZnoq uoz"!u˙N-NFS}jiklAzXafbpuu~RINKSTW0W@_ccdoe/efzggkbl`lo,wx%yIyW}󂝂rvzz7~TwUUXuc/d"fIfKhmikm%nsthtu[uvwwy~ ~/:ю돰2csOSYZ^hNtuyz̏egWoW}ݏ/_aoNOPSU]o]k!kdx{IʐncId>w@z/jdoqttz|~|~ }LR9[dg-}.PSXyaXaYaezًP P!RuU1Z<^_pa4e^f f6fino2sv!z9YքPW[[_icx&}܅!ǑQg{VQY`UPRT\:a}bbdenv `_NSCUY)]dlmszw!QTU_do}M5P\lmuw|=|dyXY^cwrRuwk܌^ftm}˗QRCfmn}.^RRTabbhiiZj5pq&x]yyyz xՃIIbOVqwׇ[_gQSXZ[`ad`~=p%dP]gXbciixjnkvy˂)ύKۚ6 Nu\y]z{Q{~.ĎYtf%i?tCQg.QE_l]w`ST9V4Z6\1pZ퍣_PtNS`n,\dOP$U\^_`ehlmquuvazzI}}n􆩏əRRGRŘ퉪NgoO[glmxtx'ݓ|yz1_NTU>XY`bSbg6iU5@P,SSUDW|bXdfkgoot"t88TQVWf_HakNpXp}Yj+cw=XTd-i[^noiQLSY*` aKklpl{΂ԍƐdodeQNTWa_hvu{R}qXí*9PxYWYb*a]ryWaZF]bddgwlm>r,t6x4wۘR$WBgrHt㌩*QkScLOiU`eWlmrLrz_mopaOPObArG{}MWj^sg UT [^c^_ e=[OHSS STTW^`bbcUlmfux2ށ/ބa ^EffprOR}_jaSgSjotyhhyǘĚCTziSJ_|buvBS9_<_lsubu{FNO\c>myrϘ0NQDRW_blnppPpqstiJaQn_W`agfYJNNNT|XXY}\_'b6bHf fgkmimnVnooop]rt%tZtvy\|~ႦkN_twje`bwZZfmn>t?B_`{T_l^lm*p}y ;ST[j:pkuuyyqAt de+xxzkN8UYP[^{`ckafehSnqet}i%m;ns>AQ^L_`M`a0aLfCfDiln_nobqLtv{|'RWQS/V^_`b`affgjmoppsj~j4ԊRsr[jkTV[]eHefhmmr;uMOPSTT?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   & ! 0` 9Zd}y     "  !"a :[e~zA^{B_=>|T9 CGPXnpbU: DHQYoqcEncodings/README000044400000003636152344545640007357 0ustar00This directory contains binary encoding maps for some selected encodings. If they are placed in a directory listed in @XML::Parser::Expat::Encoding_Path, then they are automatically loaded by the XML::Parser::Expat::load_encoding function as needed. Otherwise you may load what you need directly by explicitly calling this function. These maps were generated by a perl script that comes with the module XML::Encoding, compile_encoding, from XML formatted encoding maps that are distributed with that module. These XML encoding maps were generated in turn with a different script, domap, from mapping information contained on the Unicode version 2.0 CD-ROM. This CD-ROM comes with the Unicode Standard reference manual and can be ordered from the Unicode Consortium at http://www.unicode.org. The identical information is available on the internet at ftp://ftp.unicode.org/Public/MAPPINGS. See the encoding.h header in the Expat sub-directory for a description of the structure of these files. Clark Cooper December 12, 1998 ================================================================ Contributed maps This distribution contains four contributed encodings from MURATA Makoto that are variations on the encoding commonly called Shift_JIS: x-sjis-cp932.enc x-sjis-jdk117.enc x-sjis-jisx0221.enc x-sjis-unicode.enc (This is the same encoding as the shift_jis.enc that was distributed with this module in version 2.17) Please read his message (Japanese_Encodings.msg) about why these are here and why I've removed the shift_jis.enc encoding. We also have two contributed encodings that are variations of the EUC-JP encoding from Yoshida Masato : x-euc-jp-jisx0221.enc x-euc-jp-unicode.enc The comments that MURATA Makoto made in his message apply to these encodings too. KangChan Lee supplied the euc-kr encoding. Clark Cooper December 26, 1998 Encodings/iso-8859-7.enc000044400000002060152344545640010525 0ustar00ISO-8859-7  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   z Encodings/Japanese_Encodings.msg000044400000011325152344545640012720 0ustar00Mapping files for Japanese encodings 1998 12/25 Fuji Xerox Information Systems MURATA Makoto 1. Overview This version of XML::Parser and XML::Encoding does not come with map files for the charset "Shift_JIS" and the charset "euc-jp". Unfortunately, each of these charsets has more than one mapping. None of these mappings are considered as authoritative. Therefore, we have come to believe that it is dangerous to provide map files for these charsets. Rather, we introduce several private charsets and map files for these private charsets. If IANA, Unicode Consoritum, and JIS eventually reach a consensus, we will be able to provide map files for "Shift_JIS" and "euc-jp". 2. Different mappings from existing charsets to Unicode 1) Different mappings in JIS X0221 and Unicode The mapping between JIS X0208:1990 and Unicode 1.1 and the mapping between JIS X0212:1990 and Unicode 1.1 are published from Unicode consortium. They are available at ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0208.TXT and ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0212.TXT, respectively.) These mapping files have a note as below: # The kanji mappings are a normative part of ISO/IEC 10646. The # non-kanji mappings are provisional, pending definition of # official mappings by Japanese standards bodies. Unfortunately, the non-kanji mappings in the Japanese standard for ISO 10646/1, namely JIS X 0221:1995, is different from the Unicode Consortium mapping since 0x213D of JIS X 0208 is mapped to U+2014 (em dash) rather than U+2015 (horizontal bar). Furthermore, JIS X 0221 clearly says that the mapping is informational and non-normative. As a result, some companies (e.g., Microsoft and Apple) have introduced slightly different mappings. Therefore, neither the Unicode consortium mapping nor the JIS X 0221 mapping are considered as authoritative. 2) Shift-JIS This charset is especially problematic, since its definition has been unclear since its inception. The current registration of the charset "Shift_JIS" is as below: >Name: Shift_JIS (preferred MIME name) >MIBenum: 17 >Source: A Microsoft code that extends csHalfWidthKatakana to include > kanji by adding a second byte when the value of the first > byte is in the ranges 81-9F or E0-EF. >Alias: MS_Kanji >Alias: csShiftJIS First, this does not reference to the mapping "Shift-JIS to Unicode" published by the Unicode consortium (available at ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/SHIFTJIS.TXT). Second, "kanji" in this registration can be interepreted in different ways. Does this "kanji" reference to JIS X0208:1978, JIS X0208:1983, or JIS X0208:1990(== JIS X0208:1997)? These three standards are *incompatible* with each other. Moreover, we can even argue that "kanji" refers to JIS X0212 or ideographic characters in other countries. Third, each company has extended Shift JIS. For example, Microsoft introduced OEM extensions (NEC extensionsand IBM extensions). Forth, Shift JIS uses JIS X0201, which is almost upper-compatible with US-ASCII but is not quite. 5C and 7E of JIS X 0201 are different from backslash and tilde, respectively. However, many programming languages (e.g., Java) ignore this difference and assumes that 5C and 7E of Shift JIS are backslash and tilde. 3. Proposed charsets and mappings As a tentative solution, we introduce two private charsets for EUC-JP and four priviate charsets for Shift JIS. 1) EUC-JP We have two charsets, namely "x-eucjp-unicode" and "x-eucjp-jisx0221". Their difference is only one code point. The mapping for the former is based on the Unicode Consortium mapping, while the latter is based on the JIS X0221 mapping. 2) Shift JIS We have four charsets, namely x-sjis-unicode, x-sjis-jisx0221, x-sjis-jdk117, and x-sjis-cp932. The mapping for the charset x-sjis-unicode is the one published by the Unicode consortium. The mapping for x-sjis-jisx0221 is almost equivalent to x-sjis-unicode, but 0x213D of JIS X 0208 is mapped to U+2014 (em dash) rather than U+2015. The charset x-sjis-jdk117 is again almost equivalent to x-sjis-unicode, but 0x5C and 0x7E of JIS X0201 are mapped to backslash and tilde. The charset x-sjis-cp932 is used by Microsoft Windows, and its mapping is published from the Unicode Consortium (available at: ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.txt). The coded character set for this charset includes NEC-extensions and IBM-extensions. 0x5C and 0x7E of JIS X0201 are mapped to backslash and tilde; 0x213D is mapped to U+2015; and 0x2140, 0x2141, 0x2142, and 0x215E of JIS X 0208 are mapped to compatibility characters. Makoto Fuji Xerox Information Systems Tel: +81-44-812-7230 Fax: +81-44-812-7231 E-mail: murata@apsdc.ksp.fujixerox.co.jp Encodings/iso-8859-15.enc000044400000002060152344545640010604 0ustar00ISO-8859-15  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ `a}~RSxEncodings/x-sjis-jisx0221.enc000044400000043432152344545640011661 0ustar00x-sjis-jisx0221(%  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|} >abcdefghijklmnopqrstuvwxyz{|}~\@@OL@@^@c@ @@@W@@@@ K@ @ @ @ ?@ @ @v@3@@@j@'@@@^@@@@R@@@@F@@e > abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'000 000@>?00000N0000  \0 \ & %     00;=[]00 0 0 0 0 0000 ""`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%BNUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{Qyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQqEncodings/windows-1252.enc000044400000002060152344545640011235 0ustar00windows-1252  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   & ! 0` 9R}     "  !"a :S~xEncodings/windows-1251.enc000044400000002060152344545640011234 0ustar00windows-1251  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ S  & ! 0 9   R     "  !"Y :Z\[_^VQ!TXUW !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOEncodings/iso-8859-3.enc000044400000002060152344545640010521 0ustar00ISO-8859-3  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~&$0^4{'%1_5|  l\  !m]Encodings/ibm866.enc000044400000002060152344545640010167 0ustar00ibm866  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>?%%%%%$%a%b%V%U%c%Q%W%]%\%[%%%4%,%%%<%^%_%Z%T%i%f%`%P%l%g%h%d%e%Y%X%R%S%k%j%% %%%%%@ABCDEFGHIJKLMNOQTW^""!%Encodings/iso-8859-9.enc000044400000002060152344545640010527 0ustar00ISO-8859-9  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0^1_Encodings/koi8-r.enc000044400000002060152344545640010265 0ustar00koi8-r  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~%%% %%%%%$%,%4%<%%%%%%%%# %"""H"d"e#!%P%Q%RQ%S%T%U%V%W%X%Y%Z%[%\%]%^%_%`%a%b%c%d%e%f%g%h%i%j%k%lN01F45D3E89:;<=>?O@ABC62LK7HMIGJ.&$%/ !"#,+(-)'*Encodings/x-sjis-unicode.enc000044400000043432152344545640012025 0ustar00x-sjis-unicode(%  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|} >abcdefghijklmnopqrstuvwxyz{|}~\@@OL@@^@c@ @@@W@@@@ K@ @ @ @ ?@ @ @v@3@@@j@'@@@^@@@@R@@@@F@@e > abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'000 000@>?00000N0000  \0 \ & %     00;=[]00 0 0 0 0 0000 ""`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%BNUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{Qyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQqEncodings/windows-1255.enc000044400000002060152344545640011240 0ustar00windows-1255  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   & ! 0 9     "  !" :   Encodings/x-sjis-cp932.enc000044400000047620152344545640011242 0ustar00x-sjis-cp932.  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~abcdefghijklmnopqrstuvwxyz{|}~\g@@O^@@@]?@^t@@@L@ @@@@@@ @ w@ 4@ @ @ k@(@@@_@@@@S@@@@G@@@~@;@@@r@e/@@Q@@@ \~ abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-000 000@>?00000N0000  <^"%\ & %     00;=[]00 0 0 0 0 0000 "`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%B$`$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s!`!a!b!c!d!e!f!g!h!i3I33"3M33'3363Q3W3 3&3#3+3J3;33333333{00!3!!222222122293~3}3|"R"a"+"."""" """5")"*NUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{Qyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQq~HOpf1hȒf_EN(NNOOO9OVOOOOOP@P"OPPFPpPBPPPQJQdQQQRRRRRSSS$SrSSSTTTTUWYWeWWWXXY YSY[Y]YcYY[V[u/[[\\\\]']S]B]m]]]_!_4_g__`]````a `aa7a0abbcd`ddeNfff;f f.ff$fefWfYfsfffffg)gfghRghhDhihiij0jkjFjsj~jjkl?l\llolmmmommmmmmn9n\n'n?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~g?gL?^^PCKSVL8Q +^K^^^e^^!^^^;^^^U^^^o^^ +^ ^ ^ E^ ^ ^ _^ ^ ^ y^ ^ 5^ ^ ^O3^^>^^^X^^^r^^.^^^H^^^b^^^|^^8^^^R^^^l^^(^^^B^^^\^~Ca=}0VWWA^^^T^^^n^^ *^ ^ ^!D^!^"^"^^"^#^#x^#^$4^$^$^%N^%^& ^&h^&^'$^'^'^(>^(^(^)X^)^*^*r^*^+.^+^+^,H^,^-^-b^-^.^.|^.^/8^/^/^0R^0^1^1l^1^2(^2^2^3B^3C3  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOabcdefghijklmnopqrstuvwxyz{|}~PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~000 000@>?00000N0000  \0 \ & %     00;=[]00 0 0 0 0 0000 ""`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%BNUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{QĐyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQq~!"!    RSTUVWXYZ[\^_&2A?JRf'138B@IKSg  " $0*.(469=;CGEPLTXVZ\`^dblpjrnhtxvy}{   !%+/)57:><DHFQMUYW[]a_ecmqksoiuwz~|NNNN NNN#N$N(N+N.N/N0N5N@NANDNGNQNZN\NcNhNiNtNuNyNNNNNNNNNNNNNNNNNNNNNNOOOOO O OOOOOO.O1O`O3O5O7O9O;O>O@OBOHOIOKOLOROTOVOXO_OcOjOlOnOqOwOxOyOzO}O~OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPP P PPPPPPPPPP"P'P.P0P2P3P5P@PAPBPEPFPJPLPNPQPRPSPWPYP_P`PbPcPfPgPjPmPpPqP;PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQ Q Q QPQQQQQQQQ#Q'Q(Q,Q-Q/Q1Q3Q4Q5Q8Q9QBQJQOQSQUQWQXQ_QdQfQ~QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRR"R(R1R2R5RSBSLSKSYS[SaScSeSlSmSrSyS~SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTT!T'T(T*T/T1T4T5TCTDTGTMTOT^TbTdTfTgTiTkTmTnTtTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUUU U U UUU*U+U2U5U6U;UW?WEWFWLWMWRWbWeWgWhWkWmWnWoWpWqWsWtWuWwWyWzW{W|W~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXX WX X XXXX X&X'X-X2X9X?XIXLXMXOXPXUX_XaXdXgXhXxX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYY Y YYYAYY!Y#Y$Y(Y/Y0Y3Y5Y6Y?YCYFYRYSYYY[Y]Y^Y_YaYcYkYmYoYrYuYvYyY{Y|YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZ Z ZZZZZ#Z$Z'Z(Z*Z-Z0ZDZEZGZHZLZPZUZ^ZcZeZgZmZwZzZ{Z~ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[4[[[[![%[-[8[A[K[L[R[V[^[h[n[o[|[}[~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\ \\\\#\&\)\+\,\.\0\2\5\6\Y\Z\\\b\c\g\h\i\m\p\t\u\z\{\|\}\\\\\\\\\\\\\\\\\\\\\\\\\]]] ]]+]#]$]&]']1]4]9]=]?]B]C]F]H]U]Q]Y]J]_]`]a]b]d]j]m]p]y]z]~]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^ ^^^^^^ ^.^(^2^5^>^K^P^I^Q^V^X^[^\^^^h^j^k^l^m^n^p^^^^^^^^^^^^^^^^^^^^^^^^^^_________!_"_#_$_(_+_,_._0_4_6_;_=_?_@_D_E_G_M_P_T_X_[_`_c_d_g_o_r_t_u_x_z_}_~________________________________________`` ` ```````$`-`3`5`@`G`H`I`L`Q`T`V`W`]`a`g`q`~``````````````````````````````````````````aaa a aaaaaaaaaaa"a*a+a0a1a5a6a7a9aAaEaFaIa^a`alaraxa{a|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbb b"b#b'b)b+b9b=bBbCbDbFbLbPbQbRbTbVbZb\bdbmbobsbzb}bbbbbbbbbbbbbbbbbbbbbbccc c c ccccc)c*c-c5c6c9cgEgGgHgLgTgUg]gfglgngtgvg{gggggggggggggggggggggggggggggggggghRhhhhh(h'h,h-h/h0h1h3h;h?hDhEhJhLhUhWhXh[hkhnhohphqhrhuhyhzh{h|hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhii i iiiiii1i3i5i8i;iBiEiIiNiWi[icidieifihiiilipiqirizi{iiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjj j$j(j0j2j4j7j;j>j?jEjFjIjJjNjPjQjRjUjVj[jdjgjjjqjsj~jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkk kkkkkkk$k(k+k,k/k5k6k;k?kFkJkMkRkVkXk]k`kgkkknkpkuk}k~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllll l llllll&l'l(l,l.l3l5l6l:l;l?lJlKlMlOlRlTlYl[l\lklmloltlvlxlyl{llllllllllllllllllllllllllllllllmmm mmmmmm&m'm(lgm.m/m1m9mu?u@uCuGuHuNuPuRuWu^u_uauouquyuzu{u|u}u~uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvvvvv v vvvvvvvvvvv#v%v&v)v-v2v3v5v8v9v:vwBwEwFwJwMwNwOwRwVwWw\w^w_w`wbwdwgwjwlwpwrwswtwzw}wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxx x xxxx!x"x#x-x.x0x5x7xCxDxGxHxLxNxRx\x^x`xaxcxdxhxjxnxzx~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyxxxxxyy yyyyyy y%y'y)y-y1y4y5y;y=y?yDyEyFyJyKyOyQyTyXy[y\ygyiykyryyy{y|y~yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyzzzz z z zzzzz!z'z+z-z/z0z4z5z8z9z:zDzEzGzHzLzUzVzYz\z]z_z`zezgzjzmzuzxz~zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{{#{'{){*{+{-{.{/{0{1{4{={?{@{A{G{N{U{`{d{f{i{j{m{o{r{s{w{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{|||||| | | ||||| |%|&|(|,|1|3|4|6|9|:|F|J|U|Q|R|S|Y|Z|[|\|]|^|a|c|g|i|m|n|p|r|y|||}|||||||||||||||||||||||||||||||}}}} }}}}}}}}#}&}*}-}1}<}=}>}@}A}G}H}M}Q}S}W}Y}Z}\}]}e}g}j}p}x}z}{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}~}}}}}}}}}}}~~~~~~~~ ~'~(~,~-~/~3~6~?~D~E~G~N~P~R~X~_~a~b~e~k~n~o~s~x~~~~~~~~~~~~~<;=>?CDGORS[\]acdefmq}~  $&,.04579:<>@D`dfmquȀ̀πҀԀՀ׀؀  $',05:@CEMX]adeoqr{ȇɇʇ·Շևهڇ܇߇ (-.025:@BEFIORWZ[\abcknpsuz{|}ԉՉ։׉؉ "$&+,/57=>@CEGIMNSVWX\]aeguvwyz{~ÊƊȊɊʊъӊԊՊ׊݊ߊ  -07EGIKOQSTWX[]Ycdfhimsuv{~ŌƌɌˌό֌Ռٌ݌ eilnōƍǍȍʍ΍эԍՍ׍ٍ  !"#&'136789=@AKMNOT[\]^abilmopqyz{ÎĎǎώюԎ܎ !#%'(,-.4567:@ACGOQRSTUX]^eƏʏˏ͏ЏҏӏՏ ()/*,-347?CDL[]bfglpty̐ÐĐŐǐȐՐאِؐܐݐߐҐ  %"#')./14679:<=CGHOSWYZ[adgmtyz{‘Ñőӑԑבّڑޑ #$%&(./035689:<>@BCFGJMNOQXY\]`aeghinopuvwxy{|}’ÒŒƒǒȒ˒̒͒ΒВӒՒגْؒܒݒߒ !$%')*3467GHIPQRUWXZ^degijmopqstvz}ēœƓǓɓʓ˓͓̓ӓٓܓޓߓ ./1234;?=CEHJLUY\_achkmnoqrxy~ƕȕɕ˕Еѕҕӕٕڕݕޕߕ"$%&,13789:<=ARTVWXant{|~ʖ]ؖږݖޖߖ !"#(13ACJNOUWXZ[cgjnsvwx{}ėŗǗɗʗ̗͗ΗЗїԗחؗٗݗޗۗ   #&+./0235%>DGJQRSVWYZbcefjl˜ŘȘ̘"&'+123459:;<@AFGHMNTXY[\^_`Ùəәԙٙڙܙޙ  "#$'-.3568GADJKLNQTV]ÚƚȚΚКҚ՚֚ךۚܚ  &+-34579:=HKLUVW[^acefhjklmnsuwxyǛțΛЛכ؛ݛߛ "#&'()*1567=ACDEIJNOPSTVX[]^_cij\khnpruw{ /0234:?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Y@Y@@@W@@@@S@@@@O@ @ @ @ K@ @ @ @G@@@@C@@@@?@@@|@;@@@x@7@@@t@1@@@n@ -@ @!@"j@#)@#@$@%f@&%@&@'@(b@)!@)@*@+^@,@,@-@.Z@/@/@0@1V@2@2@3@4R@5@5@6@7N@8 @8@9@:J@; @;@<@=F@>@>@?@@B@A?  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX0 00 "0 & %PdRTUVW\ 1 34O 56[]78009:00;<0 0 =>00 ?@0 0 AB00CDYZ[\]^    00 5 2 ;0%%%%%&&%%%%%%2! >?IJMNKL_`a ""f"g"`""R"abcdef"<")"*"" ""33"+"."5"4&@&B&A& !!!!!!!!"%"#<0 !! ijk333333333QYQ[Q^Q]QaQcUt|%%%%%%%%%%%%%%%%<%4%,%$%%%%%% %%%%m%n%p%o%P%^%j%a%%%%%q%r%s!`!a!b!c!d!e!f!g!h!i0!0"0#0$0%0&0'0(0)SD!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ11111 1 1 1 1 1111111111111111111 1!1"1#1$1%1&1'1(1)NNYNNNCN]NNNQ?QeQkQRRRSSAS\SN N NN N+N8QNENHN_N^NNQ@RRSCSSWXYY'Ys[P[Q[S[\\"\8\q]]]]]]^r^_ _bMNNN N-N0N9NK\9NNNNNNNNNNNNNNNQCQAQgQmQnQlQQRRRRRRSS9SHSGSES^SSSSXY)Y+Y*Y-[T\\$\:\o]^{^___bb6bKbNe/eeeeefgg(k kbkykkkll4pkr*r6r;rGrYr[rsNNNNNN;NMNONNNNNNNNNNNNQEQDQQQQQQR RRSSSSNSJSISaS`SoSnSSSSSSSSSSSSSSSSSSSSVVYY.Y1YtYv[U[\<]]]^^^s^|____b bSbTbRbQeeg.g,g*g+g-kcklll8lAl@l>rssttuuu(u)u0u1u2u3uv}vvvwwwy:yztzNNNRNSNiNNNNNO OO OO OOONNNNNNOO QIQGQFQHQhQqQQRRRRRRSS!S SpSqT TT T TTT TTT TTTTTVVVW3W0W(W-W,W/W)YYY7Y8YYxYY}YyYY[W[X[[[[[\\y]^^v^t____bb b bbcb[bXe6eeeeffg g=g4g1g5k!kdk{ll]lWlYl_l`lPlUlal[lMlNppr_r]v~z|s|6 3 nr~k@Lc!N2NOMOOOGOWO^O4O[OUO0OPOQO=O:O8OCOTOT&TNT'TFTCT3THTBTT)TJT9T;T8T.T5T6T TWPWOW;XY>YYYYYYYYYYYY[][\[Z[[[[[\,\@\A\?\>\\\\]^ ^^^^___d_b_w_y________bbbbbbbvbbmbb|b~bybsbbobbnbbbbe9e;e8efg_gNgOgPgQg\gVg^gIgFg`gSgWkeklBl^llllllljlzllpllhlll}llrl~ltllvllllpvp|p}pxrbrar`rrsu,u+u7u8vvwyyyzv|UoҊ7FUdpʏƏŏ]ᐑIƑ̖2.1*,N&NVNsNNNNNOoOOOsOOlOOOOOpOuOOiO{OO~OOOzQTQRQUQiQwQvQxQQR;R8R7R:R0R.R6RARRSRSTSSSQSfSwSxSySSSTsTuTTxTTT{TwTTTT|TTqTvTTTbThTT}TVWWwWjWiWaWfWdW|YYIYGYHYDYTYYYYYYYYYYYYYYYY[_[d[c[[[[[[\\H\E\F\\\\\\\^^^^^^^x^^^^^^_&_'_)____|_____```/`5``*``!`'`)`+`bbb?b>b@bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbe>eeefff fffffff fg g gmgggqggsgwggggogpggg~gguggg|gjgrk#kfkgkllllllllllllllllllllllllllllllllllpppppr,r-r8rHrgrirrrrrsssssu=uuuvvvvwwy>y@yAyyzzzyz|T NqRhˏΏԏѐǑѕw@?;DBR^NNNOOOOOOOOOOOOOOOOOOOOOOQWQQQRNRCRJRMRLRKRGRRRRS SWS{SSTTTTTTTTTTTTTTTTTTTTTTVWWWWWWWWYUYQYOYNYPYYYYYZYYYYZY[i[[[[[\\N\O\M\K\\]^^%^^}^^^__-_e_______``` `%``(`M`p`h`b`F`C`l`k`j`dbAbcc bbcbbcbbbbbbcce?eEeeef%f-f f'f/ff(f1f$fgggggggggggggggggggggggggkjkkkkkllm m2m*mAm%m m1mmm;m=m>m6mlm9m'm8m)m.m5mm+pppppppppr0rrrortrrrsssssssuu-uOuLuNuKuuuuuvxvvvvvvvwvvw w vvwwxxx x yFyIyHyGyyyyyzzzz|}}}}} }}}8 6րڀÀĀ̀ۀ΀ހ݁"ۂ ҂ׂ܂Ԃтނӂ߂Py{zMkԊts͎̏ʐΐÑKJ͕PKLMbi˗ۘߙNXNP P P#OP&P%OP)PPPc/cUcBcFcOcIc:cPc=c*c+c(cMcLeHeIeeefBfIfOfCfRfLfEfAfgggh!h8hHhFhSh9hBhTh)hhhLhQh=ghPh@hSfUFUjUfUDU^UaUCUJU1UVUOUUU/UdU8U.U\U,UcU3UAUWWW W WXX XWWWXX5WWY YbZ6ZAZIZfZjZ@ZwUUUUUU~UUUW X/X*X4X$X0X1X!XX XXY`ZwZZZZZ[s[q[[[[\ \ \1]L]P]4]G]^E^=^@^C^~^^^^_<_m___`````aa#`a```ah`a`a aabbIccccccccccccccccvcccdRcce^efebeceeefnfpftfvfoffzf~fwffgghhhhhihhhhhhhhhhi iihhinhk>k:k=kkkkl.l/l,n/n8nTn!n2ngnJn n%n#nn[nXn$nVnnn-n&non4nMn:n,nCnn>nnnnNncnDnrnin_qqq&q0q!q6qnqrLrrs6s%s4s)t:t*t3t"t%t5t6t4t/tt&t(u%u&ukujuuuuuuuv{v|vvvvwOwx]xlxoz zz zzzzzzz{I{V{F{P{R{T{M{K{O{Q||}^}P}h}U}+}n}r}a}f}b}p}sUՀ RUTKQN9F>LSt ń W ̃ʄ8܄ԃ߆[߆نԆۆІވWˆ;`U^a4a'a aa7b!b"dd>dd*d-d=d,dddd d6dddeleeffffffffgiimiZiwi`iTiui0iiJihiki^iSiyii]ici[kGkrkkkknnnnnnnnnnnnnnnnnnnnnnqNqYqiqdqIqgq\qlqfqLqeq^qFqhqVr:rRs7sEs?s>totZtUt_t^tAt?tYt[t\uvuxvuvuuuuuuvvw[wkwfw^wcwywjwlw\wewhwbwxxxxxxx|xxxyzyy,yzzz zzzzz{w{{`{n{g|||}}y}}}}[nijrVXqpxenskyzfGw=1ufkIl[<5acimF^\_ Y߈Ԉو܈؈݈ʈՈ҉krsfip|cqmbnly{>hbʌnjȌČ̌ōߍ掲 KJSBTAljiɒ7W8=@>[KdQ4IME9?Z͖˖ɖʖVtv  鞂 PPPPPPPPPPPPQbQRRS1SUVVVUVVV V VUVVVVUWWXuX~XXXXyXX}XY%Y"Y$YjYiZZZZZZZ[u[[[[[[[[[\ \b]]^[^c^U^W^T^^_ _F_p_aGa?aKawabaca_aZaXaub*ddXdTddxd_dzdQdgd4dmd{ereeefffiiiiiiiiiiiiiiiiiiikIkLl3o3onono)o>o o,ooo"nnoo1o8o2o#oo+o/oo*nonnnqqq}qqqr>rrsDsPtdtctjtptmuuv'v v v vvvww}wwaxxxxxxyyyz.z1zzzz{{{{u{{{{{{{|||}}}}}}}}}}}}}}}}}}}p߀^ZPKɄƄĄ˄ӄфʇ?;"%4U7)jӌьҍk`X\cY^b][uxwtx{|̖җ| AB󞼟;JQQPPPQQQ QQRRRRRRSV.V;V9V2V?V4V)VSVNVWVtV6V/V0XXXXXXXXYm[ Z[ Z[ [[[[[\d\e]]^b^_^a^^^^^^_H_q__avagana]aUaa|apaka~aaaaaaaaab.didodyddddddddddddddddddeuewexffffj#jijjjij!jj ijjijkPkNkkko?o|ooQofoToomo[oxonoozopodooXnooo`o_qqqqrVrsNsWtittt~tuv v)vv$v&v!v"vvvwwwwwxxxxxxxxz?z~F~7~2~C~+~=~1~E~A~4~9~H~5~?~/DqrposƁÁɁ q~gч҇Ƈȇˉ;6D8= A?sIKHJD>BE?}9M(uJeK~l[pZTʕ˕̕ȕƖ֗ӘF5;?Ϟޞܞݞ۟>KSVVXX[8_]ab3dddedddefg&jjjjjjjjk_kxkp p opoppqqqqswsuttuvVvXvRwwwwyyzazbz`zz|+|'|*||#|!|~T~U~^~Z~a~R~YHwv́ς υͅЅɅ(9,+PYcfd_UIMГԕ֕ЕՖܖٖۖޗ$MOLNS>?=.ONMʛɛțQ]`,Q3VXXX[^aaaaeeffjjjjppp(pppprr rXrsxsztttuuv_vawyyzkzi|>|?|8|=|7|@~k~m~y~i~j~s؅݅Յ `_V^A\XIZNOFY |rvlztTNѓߓÓȓܓݓ͓֓ؓדܖ*'aܗ^X[EI ֛۝arjlRVVVVVX[@[C[}[]aaeeefg'jp>p0p2rs{tvbvey&y*y,y+zz|L|C|M||~}~|~Lڂf  dplfo_k ˔0ęRQ+075 y/_caQ7Q8VVVY\l]aaeeefjkjkpLrrttviw|P~~-#"!jltw}_.35:82+892geWEC@>ϛTQ-%\fgQ×kUUMқI1>;ӝן4ljV]be#e+e*fktz|d|c|e~~~8?1c`dho\Z[WӚԚќTWV垟VXe,p^vqvrwP69bwjBHDƘp_"X_|}wr^kpc|l|n;rpq^֛#pdwڋwɚbe~Ŕ}~|wxTr(j1|r00000A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO$`$a$b$c$d$e$f$g$h$i$t$u$v$w$x$y$z${$|$}NBN\QSSNN NGNV \n_sNQNN.NNNNQRSlSW YY,\]ekklr?N1Ng9g8g;g:g?gOgORO_OAOXO-O3O?OaQQRRR!RRS ScSrSST0T7T*TTTETTT%TT=TOTAT(T$TGVVVWAWEWLWIWKWRYY@YYYYYYYYYY[[\(\*\\\\\\\\\\]^ ^^^^^^___x_v______________`_b:bbbbbbbqb{bzbpbbbwb}brbte7eeeeegEgGgYgUgLgHg]gMgZgKklllxlglkllllqlolillmllllflslel{lptpzrcrrrrrrrsssssu:u9uuvy=4xɏ0(/-N3OO|OO}OOOvOtOOOwOLOOjOOyOOxOOOOOOOOkOnQQQR5R2R3RFR1RS S SuuvvvvvwwwwwwyBy?yzxz{z|u|5 ‚ÂpomnVҏˏӏ͏֏Տא9=<:COOOOOOOOOOOOOOOOOOORDRIRRS=S|SSSSTTTTTTà TTTTTTTTpTTTTrTTWWWWWWWWWWWWWWWXY YSYYYZYYYYYYYYYYYYYYYYY[\L\\\\\\\\\\\\\\\\\\\\]^!^"^#^ ^$^^^^^^__._V_`7`9`T`r`^`E`S`G`I`[`L`@`B`_`$`D`X`f`nbBbCbc c bccbbcc bbcccbcbbeAeCeef6f!f2f5ff&f"f3f+f:ff4f9f.ggggggggggggggggggggggggggggggggggggggggggk(kkkkkkl l!m(m4m-mm9/%3-DQ%V?A&"BN*ZMZ9ZLZpZiZGZQZVZBZ\[r[n[[\Y]] ]]] ] ](] ]&]%]]0]]#]].^>^4^^^^^_6_8___`````````````````````c2ceccc}ccccccccocccnccuccmcc|cc;ccxcccccpeSefefaf[fYf\fbghyhhhhmhnhhiVhohhhhuhthhhwhh|hkhrhhhqh~hhhhhhhxh{hhhh}k6k3k7k8kkkkkl*mmmmntmmmmmmnmmmmmmmmmmmmmmmmmmmmmmmmmmmpq pqpq pqpqppqqqppq qqr~r{r|rssssss srssssssttsttssst t studucuuuuuuuvvvw9w/w-w1w2w4w3w=w%w;w5xHxRxIxMxJxLx&xExPydygyiyjycykyayyyyyzzz{5{G{4{%{0{"{${3{{*{{1{+{-{/{2{8{{#||||}5}=}8}6}:}E},})}A}G}>}?}J};}(cɀGCH%-,!'"83:42tzstu}~vYV†ņȆ̆ÆR։ىՊ0',9;\]}}{y؎ގݎ܎׎$  !ԐVXZSUz|mkqoj噗PPPPPPPPPPPhPPPPQ_QSSSSUUUUUwVEUUUUUUUUUU}UUUUUUW X)X7XXX'X#X(WXHX%XXX3X?X6X.X9X8X-X,X;YaZZZZzZZZxZZ|ZZZZZ7ZZZZZZZ{Z}ZZZZZ[[[[[[[\ \0]7]C]k]A]K]?]5]Q]N]U]3]:]R]=]1]Y]B]9]I]8]<]2]6]@]E^D^A_X___``````a`a aa`a````aaaa`aa bJccccccccdcccccccdaccccccccccccccce2egejede\eheeeeeeeef|flf{ffqfyfjfrgi hihi*hhhihhhhhiihhihiiphihhihhhhhi i ihhhhhhhihhii%hk9k;k?k?ef׀QOPԁCJROG=M:<=?u;σ#ƃȃヿ݃؃˃΃փɄ ބƒՃǃуÃă׃ۃ؆ӆچ݆܆׆шHVU׈ɉ݉ډۊNM9Y@WXDERHQJLO_؍Ӎ͍Ǎ֍܍ύՍٍȍ׍Ŏ-4/,ad_b` %& '${~–ȖÖlpnNNNPPPPPPPPPPPPPPPPPQRzRxR{R|UUUUUUUUUUUUUUUUUUUUUUUWXSXhXdXOXMXIXoXUXNX]XYXeX[X=XcXqXZZZZZZZZZZZZZZZZZZZZ[[[\\3]q]c]J]e]r]l]^]h]g]b]^O^N^J^M^K^^^^^_@__`aIaJa+aEa6a2a.aFa/aOa)a@b hb#b%b$cccddd d d$d3dCdddd9d7d"d#d d&d0d(dAd5d/d dd@d%d'd cdd.d!deoeefffffffffxg ifi_i8iNibiqi?iEiji9iBiWiYiziHiIi5ili3i=iehixi4iii@ioiDiviXiAitiLi;iKi7i\iOiQi2iRi/i{iF 2*-<:15B&'8$0뉝芫=hiՌό׍   # "$!zrysvzy}~-X}z~{Ηٙ͘ǚ>?`a_PQQ0PQQPPQ Q PQ RRRRVHVBVLV5VAVJVIVFVXVZV@V3V=V,V>V8V*V:WXXXXXXXXXXZZZZZ[Z[Z[[[[\g]]]]]]]]]]]]^i^]^`^\}^^^_I_aaayaaaaaaaaaaaaaafab-dndpddddddddddddhddevezeye{eefffffffjjjiijiij iiijjij'iijiij@jiij iij jjj%jij&jijkQkkkkllkloAo&o~oooooooboOooZoovolooUoroRoPoWooo]ooaoko}ogooSooiooocowojo{qqqqqqqqqqqqqqqqqrrsXsRs^s_s`s]s[sasZsYsbtttttt}ttt|tyuuu~v%vvvvv#vv(vvvvvwwwwxxxxxxxxxxxyyyyyykvz9zzz{{{{{{{{{||||}}}}}}~}}}}}}}vdgOSRPNQ$;)  '+ *(.1& 0 /bVcdwsXT[RaZQ^mjPN_]olzn\eO{ubgiZ   ϊƊӊъԊՊ׊Ŋ؊Êٌ>Mߌٌڌ݌獠 #%$.&',$ #spogk/+)*2&.ВÒĒْϒߒؒגݒ̒’ʒȒΒ͒Ւɒޒђƒ|ӗZЗϘ&)( 'ܙ͙ϙәԙΙəؙ֙˙י̚FCgtqfvuphdlӟQQQQQQS4SVpV`VnVsVfVcVmVrV^VwWWXXXXXXXX[[[[![[[[[([[ [[]]]]]]]]]]]]]^g^h^f^o^^^^^_K_aaaaaaaaaaaaddddddddddde3ee|effffffffffg#j4jfjIjgj2jhj>j]jmjvj[jQj(jZj;j?jAjjjdjPjOjTjojij`j[qNnuUg`f]Telcedy&0-.'1")#/,݋ߊȊފln3>8@E6<=A0?6.52974vy{356'z8<#F- ˓%4$)95* ͕ԗ 5/2$')皹3|~{z}% )"՞֞=Q&Q%Q"Q$Q Q)RVVVVVVV~VVVXXXX[-[%[2[#[,['[&[/[.[{[[]^l^j__aaaaaaaaaddddddeeeefjjjjjjjjjjjjjjjjjjjjjjjk[kl ooooooooooooooqqqqqqqsssnsotttttttttuuuuuvCvHvIvGvvwwwwwwwwwxxyxxxyxxyyyz\z[zVzXzTzZzzz||{|{{|{| {|| ||{{|{{|| |~-~<~B~3H~8~*~I~@~G~)~L~0~;~6~D~:E~},ā́ʁŁǁ[Z\{w|zxWyvhŇɇLJ̇ćʇއ53<>AR7B " OprqooNMSPLGC@~8dVG|X\vIPQ`mLjyWUROqw{a^cgNYǕɕÕŕ ՗ԗADJIEC%+,*32/-10H3Ag6./180EBC>7@=-Ȟڞ$#"TQ1Q-Q.VVVVVVYp[<\i\j]^m^naaaaaaaaaadeddeedeefffjjjjjjjjjjjk^kl pp p ppppopop&oop rqqrqsvttttttttuuv\vdvYvPvSvWvZvvvwwxy yyy yyyyyz_||)|| ||-||&|(|"|%|0~\~P~V~c~X~b~_~Q~`~W~SuсЂ_^ƅŅDžą˅΅ȅŅ҆$iۇ߇ԇ܇Ӈ؇㇤ׇو݉SKOLFPQI*'#305G/<>1%7&6.$;=:Bu\b`WV^eg[Za]iTFGHK(:;>ҕӕіז]–ߖؖݗ#"%חٗ֗ؗPQRA<:  ܛ)5JLKǛƛÛӛě\SOJ[KYVLWRT_XZߟ%+*)(LUQ4Q5RRSVVVVVVXXXY[=[>[?]^p_aeee e e eeeefjjjjjjjjjjjjjk`kl pp'p pp+p!p"p#p)pp$pp*r r rrrrrrrrttttuv`wwwwyyy!yyyyzgzh|3|<|9|,|;||~v~u~x~p~w~o~z~r~t~hKJxׁՂdacمڅׅ؅߅܅хޅ  bZ[Wa\X]YPHJ@SVTKUQBRWCwv mxsjo{RQOPS@?ޓǓϓ“ړГ̓ٓʓԓՓēΓғ}ڕۖ)+,(&ݗޗߘ\Y]WHGC%$" '#›  7ޛԛכܛٛ՛ڝwqx}ktupis{oyh-@AMVWXS7VVVX[E]]^^__aeeeeefffjjjjjjjjp02.3vtsEdcbU]W^ėŘVY RXPJMKUYLNžО876COqpnoVV[N\me-ffkp_pap]p`r#ttwy8yy|j~mC875K”khiFCGǗ^՛Ycgfb^` FtuvVe.ekkkkpbr&rwwy9|i|k|~~~~FGHyz|{nmoqsIr_hnm  Gx{zyWpf|o<Ôtxvu`tsqu phpe|j>=?ɗKst̙adfg$Hbkr'Lih.r)Kyvukzpipj~IEncodings/x-sjis-jdk117.enc000044400000043432152344545640011400 0ustar00x-sjis-jdk117(%  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~abcdefghijklmnopqrstuvwxyz{|}~\@@OL@@^@c@ @@@W@@@@ K@ @ @ @ ?@ @ @v@3@@@j@'@@@^@@@@R@@@@F@@e\~ abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'000 000@>?00000N0000  \0 \ & %     00;=[]00 0 0 0 0 0000 ""`"f"g""4&B&@ 2 3! &&%%%%%%%%%%% ;0!!!!0"" """""*")"'"(!!""" "#"""a"R"j"k""=""5"+",!+ 0&o&m&j !%!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNO%%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%BNUZ?Tac(Y"uzP`cn%efhW'ebq[YІ{}b}b|[^c fhHǗgONO OMOPIVY7YZ\ `aapfipuOupy}}ÄcUzS;NNW߀xNXn8z2(/QASpTTVY_m-bpT S[p–So\zNxn&VUk;YSmftܕVBNKO SU[0_qf fhl8lm)t[vzN4[`muvʙ`iSQWX0YD[^`(cclopqqYqs?~vх`[XielZu%QY.Ye__bej*k'ksV,\l{Q\KahvraNYOSx`in)zON SNOUO=OOsRSV YZ[[yfggkLlpksyyz<{ۃwӇfV)NO\brYu;傽řNOVXJX^_`*``babbe9AffhmwppuLv}uQRYT[]ahimxˈWrmlWgΒRVT^bdhkSlWo"ooEtuvw z{|!}6f̌Qeә(N8T+\]svLw<\ TXOOSqUVhWYG[ [\^ ^~_cg:eeghhj_^0kll}uyH[cz}_w̏Z/__`hjtZxwN^NO|OPPQIQlRRRSSTTUWQWY}[T[][]]]^x^^^_`RaLbbce;ffCfgmh!hil_m*min/nu2vxlz?|}}}^}T*RLaʑuqx?M؝;R[RSTXboj_QKR;TJVz@w`sDo pu_`ښrۏkdNVWdXZZ`haffh9hmu}:nBNOPSU]o]]gltsxPWP^c+PPQgTX^Y[_ibMch=ksnp}rxx&yme}0܈ RdW(gPjQWB*X:iT]WxO\RJTd>f(ggz{V}"/h\{9SQR7[bddg-kvcLvfRN PS\q`dech_qsu#{~ۑxefkNNO:OR:SSUVXYYY[P\M^^+_`ce/[\eeegkbk{lsEyIy|}}+󉖊^ifnjܖ̘koNOtuxy: 3ꄔlP_X+z[NSWY1Z[`nou[{Prg\aJ~Q\chfeqny>}ʐnǐPR\:gSp|r5Lȓ+[_1`N;S[bKg1krsz.kRQSTj[cj9}VSTh[\1]Oabm2yy}B~MҁFrt/1KlƑNOOQESA_bglAn sc~&͒SY[my]~.|X~qQSO\f%wzQ_eiokmnodv}]uQRb@ffn^}rfRSYs^_`UdPQRS SGSTUFU1VYhYZ<[\\\\^^^_pbbbccwff f-fvg~hjj5lmn nXq d_xRbcdBb-z{}v INQHSCS`[\\]b&bGdhh4lmEmgo\qNq}ez{}~Jz9n΍xwRMUo8q6Qhy~U|VLXQ\cffiZruuyyVy|} }D4;a PRuSSP UXYOr=[\dS``c\cc?cdef]iioqNuvz|}}aIXlōpmPXaӅ5 OPtRGSs`ocIg_n,O\^e}SRQvc[X[k\ d gQ\NYY*lpQU>XY`bSg5iU@Ě(OSX[\^/_` aKb4flnހ΁Ԉ.ۛNSY'{,Lnp'SSUD[bXbblot"8o8QSSOFTYj1]zꏿhڌ7rHj=N9SXVWfbcekNmn[pwz{}=Ɔˊ[VX_>efjku7P$wW0_`efzl`uznE{u\z{Qyz6Zw@N-N[_bft6x4ZFuO^bceWgovrL̀)MP WZhisqdrXjyw)O/ReSZbglv}{|6fo r~Q{xr{{Hj^auQu`QkbnvzOpb{OVzXY䖼O4R$SJSS^d,egl>lNrHrsuT~A,錩{đqic=fiujvxЅCS*SQT&Y^_|`bIbybekluvxy}w^j |8P\>_gkt5w ;gzS9u_f_<_ub{Feg llpx2~+ނ *JҘlNONPRVWJY^=__b?fgghQ}!~2T ,SPS\Xdg4rgwfzFRlkX^LYTg,QvdixTWYf'gkTi^UggRh]NOSbg+lO~mNabno+Tsg*E]{\[ƇnJzY|lw RY"q!r_wۗ'ai ZZQT T}fvߏYr]nQMh}}bdxj!Y[_ksv}Q2g(vgbR\$b;|~UO`} SN_QYr:6_%wS_y}3Vg󅮔Sa alvR8U/OQQ*RS[^}`acg gngms6s7u1yPՊJćYNOYN?P^|Y[^ccdfiJim nqu(zIɉ! e} a~bk2lmtmge}o#,TBojp2RZA^_gi|imjorbr{~KQmy2P-Tqkjā`gNNkhin~xU_ NNN*N1N6NzYUYPYNYZYXYbY`YgYlYiYxYYO^OYYYYYYYYZ%ZZZZ ZZ@ZlZIZ5Z6ZbZjZZZZZZZZZZZZZ[ [ [[2Z[*[6[>[C[E[@[Q[U[Z[[[e[i[p[s[u[xe[z[[[[[[[[[[[[[[[[[[\\\\ \\ \"\(\8\9\A\F\N\S\P\O[q\l\nNb\v\y\\\Y\\\\\\\\\\\\\]\] ]]]\]]]]]"]]]]L]R]N]K]l]s]v]]]]]]]]]]]]]]]]]]]]^ ^^^^^6^7^D^C^@^N^W^T^_^b^d^G^u^v^z^^^^^^^^^^^^^^^^^^^^^^^__ _]_\_ ___)_-_8_A_H_L_N_/_Q_V_W_Y_a_m_s_w____________________`_`!`````)``1```+`&``:`Z`A`j`w`_`J`F`M`c`C`d`B`l`k`Y`````````````````_````aMaa``a``aa!``a aaGa>a(a'aJa?acMdcOcccccvcccccckcicccccccccdd4ddd&d6edd(ddgdodvdNe*ddddddddddddddd ddbdde,ddddedeeee$e#e+e4e5e7e6e8uKeHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeegrf fegsf5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpffffffffffffffffff?fffffgggg&g'8g.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjgggggggggggggggggggggjhhFh)h@hMh2hNhh+hYhchwhhhhhhhhjhhthhhihh~ihihi"i&hi hhhhi6iihhi%hhhi(i*ii#i!hiyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiii[iiiiij.iiiiiiijjik iiijijijij jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjjjjjjjjjjjjjjkjkk1kk8k7vk9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkklllll$l#l^lUlbljllllll~lhlslllllllllllllllllmMm6m+m=m8mm5m3mm mcmmdmZmymYmmommnn mmmmmmmmmmmmmmmmmn-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnoAopLnnno?no1no2no>onoozoxooooo[oomoo|oXoooofooooooooooooooop p opppoppotpppp0p>p2pQpcppppppppppppq pqqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqqr rrr(r-r,r0r2r;rsNsOsWsjshspsxsus{szsssssssstttot%st2t:tUt?t_tYtAt\titptctjtvt~ttttttsttttttttttuuuu uu uuuu&u,uz7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzz{{{ {{3{{{{5{({6{P{z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{||{{|`|||{{|| {|#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u|||||||||||||||||||||;|||||}}}}} }E}K}.}2}?}5}F}s}V}N}r}h}n}O}c}}}[}}}}}}}}}}}~=}}}}}}}}}}}}}~~ ~#~!~~1~~ ~ ~"~F~f~;~5~9~C~7~2~:~g~]~V~^~Y~Z~y~j~i~|~{~}~}~~~~~~~~~~~~8:ELMNPQUTX_`higxq܀ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀց )#/KF>SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ރ܃ ك5421@9PE/+#|su΃؄  " 8m*(ALONIV[Zk_lot}:A?HLNPUblxz|bȌڌ  N͍gmqsύڍ֍̍ۍˍߍ B504JGILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659OPQRI>VX^hovr}bHۑ20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD."#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~oÕ͕̕Օԕ֕ܕ!(./BLOKw\^]_frlΖ˖ɖ͉Mܗ Ֆ$*09=>DFHBI\`dfhRҗkqy|z×Ɨȗ˗ܗOzߗ 8$!7=FOKkopqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FH]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrvX/iǐYtdQqEncodings/iso-8859-4.enc000044400000002060152344545640010522 0ustar00ISO-8859-4  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~8V(;`"f}W)<a#gJ~K. *EL6rhj/ +FM7sikExpat.pm000044400000104520152344545640006177 0ustar00package XML::Parser::Expat; use strict; #use warnings; No warnings numeric?? use XSLoader; use Carp; our $VERSION = '2.46'; our ( %Encoding_Table, @Encoding_Path, $have_File_Spec ); use File::Spec (); %Encoding_Table = (); if ($have_File_Spec) { @Encoding_Path = ( grep( -d $_, map( File::Spec->catdir( $_, qw(XML Parser Encodings) ), @INC ) ), File::Spec->curdir ); } else { @Encoding_Path = ( grep( -d $_, map( $_ . '/XML/Parser/Encodings', @INC ) ), '.' ); } XSLoader::load( 'XML::Parser::Expat', $VERSION ); our %Handler_Setters = ( Start => \&SetStartElementHandler, End => \&SetEndElementHandler, Char => \&SetCharacterDataHandler, Proc => \&SetProcessingInstructionHandler, Comment => \&SetCommentHandler, CdataStart => \&SetStartCdataHandler, CdataEnd => \&SetEndCdataHandler, Default => \&SetDefaultHandler, Unparsed => \&SetUnparsedEntityDeclHandler, Notation => \&SetNotationDeclHandler, ExternEnt => \&SetExternalEntityRefHandler, ExternEntFin => \&SetExtEntFinishHandler, Entity => \&SetEntityDeclHandler, Element => \&SetElementDeclHandler, Attlist => \&SetAttListDeclHandler, Doctype => \&SetDoctypeHandler, DoctypeFin => \&SetEndDoctypeHandler, XMLDecl => \&SetXMLDeclHandler ); sub new { my ( $class, %args ) = @_; my $self = bless \%args, $_[0]; $args{_State_} = 0; $args{Context} = []; $args{Namespaces} ||= 0; $args{ErrorMessage} ||= ''; if ( $args{Namespaces} ) { $args{Namespace_Table} = {}; $args{Namespace_List} = [undef]; $args{Prefix_Table} = {}; $args{New_Prefixes} = []; } $args{_Setters} = \%Handler_Setters; $args{Parser} = ParserCreate( $self, $args{ProtocolEncoding}, $args{Namespaces} ); $self; } sub load_encoding { my ($file) = @_; $file =~ s!([^/]+)$!\L$1\E!; $file .= '.enc' unless $file =~ /\.enc$/; unless ( $file =~ m!^/! ) { foreach (@Encoding_Path) { my $tmp = ( $have_File_Spec ? File::Spec->catfile( $_, $file ) : "$_/$file" ); if ( -e $tmp ) { $file = $tmp; last; } } } open( my $fh, '<', $file ) or croak("Couldn't open encmap $file:\n$!\n"); binmode($fh); my $data; my $br = sysread( $fh, $data, -s $file ); croak("Trouble reading $file:\n$!\n") unless defined($br); close($fh); my $name = LoadEncoding( $data, $br ); croak("$file isn't an encmap file") unless defined($name); $name; } # End load_encoding sub setHandlers { my ( $self, @handler_pairs ) = @_; croak("Uneven number of arguments to setHandlers method") if ( int(@handler_pairs) & 1 ); my @ret; while (@handler_pairs) { my $type = shift @handler_pairs; my $handler = shift @handler_pairs; croak 'Handler for $type not a Code ref' unless ( !defined($handler) or !$handler or ref($handler) eq 'CODE' ); my $hndl = $self->{_Setters}->{$type}; unless ( defined($hndl) ) { my @types = sort keys %{ $self->{_Setters} }; croak("Unknown Expat handler type: $type\n Valid types: @types"); } my $old = &$hndl( $self->{Parser}, $handler ); push( @ret, $type, $old ); } return @ret; } sub xpcroak { my ( $self, $message ) = @_; my $eclines = $self->{ErrorContext}; my $line = GetCurrentLineNumber( $_[0]->{Parser} ); $message .= " at line $line"; $message .= ":\n" . $self->position_in_context($eclines) if defined($eclines); croak $message; } sub xpcarp { my ( $self, $message ) = @_; my $eclines = $self->{ErrorContext}; my $line = GetCurrentLineNumber( $_[0]->{Parser} ); $message .= ' at line $line'; $message .= ":\n" . $self->position_in_context($eclines) if defined($eclines); carp $message; } sub default_current { my $self = shift; if ( $self->{_State_} == 1 ) { return DefaultCurrent( $self->{Parser} ); } } sub recognized_string { my $self = shift; if ( $self->{_State_} == 1 ) { return RecognizedString( $self->{Parser} ); } } sub original_string { my $self = shift; if ( $self->{_State_} == 1 ) { return OriginalString( $self->{Parser} ); } } sub current_line { my $self = shift; if ( $self->{_State_} == 1 ) { return GetCurrentLineNumber( $self->{Parser} ); } } sub current_column { my $self = shift; if ( $self->{_State_} == 1 ) { return GetCurrentColumnNumber( $self->{Parser} ); } } sub current_byte { my $self = shift; if ( $self->{_State_} == 1 ) { return GetCurrentByteIndex( $self->{Parser} ); } } sub base { my ( $self, $newbase ) = @_; my $p = $self->{Parser}; my $oldbase = GetBase($p); SetBase( $p, $newbase ) if @_ > 1; return $oldbase; } sub context { my $ctx = $_[0]->{Context}; @$ctx; } sub current_element { my ($self) = @_; @{ $self->{Context} } ? $self->{Context}->[-1] : undef; } sub in_element { my ( $self, $element ) = @_; @{ $self->{Context} } ? $self->eq_name( $self->{Context}->[-1], $element ) : undef; } sub within_element { my ( $self, $element ) = @_; my $cnt = 0; foreach ( @{ $self->{Context} } ) { $cnt++ if $self->eq_name( $_, $element ); } return $cnt; } sub depth { my ($self) = @_; int( @{ $self->{Context} } ); } sub element_index { my ($self) = @_; if ( $self->{_State_} == 1 ) { return ElementIndex( $self->{Parser} ); } } ################ # Namespace methods sub namespace { my ( $self, $name ) = @_; local ($^W) = 0; $self->{Namespace_List}->[ int($name) ]; } sub eq_name { my ( $self, $nm1, $nm2 ) = @_; local ($^W) = 0; int($nm1) == int($nm2) and $nm1 eq $nm2; } sub generate_ns_name { my ( $self, $name, $namespace ) = @_; $namespace ? GenerateNSName( $name, $namespace, $self->{Namespace_Table}, $self->{Namespace_List} ) : $name; } sub new_ns_prefixes { my ($self) = @_; if ( $self->{Namespaces} ) { return @{ $self->{New_Prefixes} }; } return (); } sub expand_ns_prefix { my ( $self, $prefix ) = @_; if ( $self->{Namespaces} ) { my $stack = $self->{Prefix_Table}->{$prefix}; return ( defined($stack) and @$stack ) ? $stack->[-1] : undef; } return undef; } sub current_ns_prefixes { my ($self) = @_; if ( $self->{Namespaces} ) { my %set = %{ $self->{Prefix_Table} }; if ( exists $set{'#default'} and not defined( $set{'#default'}->[-1] ) ) { delete $set{'#default'}; } return keys %set; } return (); } ################################################################ # Namespace declaration handlers # sub NamespaceStart { my ( $self, $prefix, $uri ) = @_; $prefix = '#default' unless defined $prefix; my $stack = $self->{Prefix_Table}->{$prefix}; if ( defined $stack ) { push( @$stack, $uri ); } else { $self->{Prefix_Table}->{$prefix} = [$uri]; } # The New_Prefixes list gets emptied at end of startElement function # in Expat.xs push( @{ $self->{New_Prefixes} }, $prefix ); } sub NamespaceEnd { my ( $self, $prefix ) = @_; $prefix = '#default' unless defined $prefix; my $stack = $self->{Prefix_Table}->{$prefix}; if ( @$stack > 1 ) { pop(@$stack); } else { delete $self->{Prefix_Table}->{$prefix}; } } ################ sub specified_attr { my $self = shift; if ( $self->{_State_} == 1 ) { return GetSpecifiedAttributeCount( $self->{Parser} ); } } sub finish { my ($self) = @_; if ( $self->{_State_} == 1 ) { my $parser = $self->{Parser}; UnsetAllHandlers($parser); } } sub position_in_context { my ( $self, $lines ) = @_; if ( $self->{_State_} == 1 ) { my $parser = $self->{Parser}; my ( $string, $linepos ) = PositionContext( $parser, $lines ); return '' unless defined($string); my $col = GetCurrentColumnNumber($parser); my $ptr = ( '=' x ( $col - 1 ) ) . '^' . "\n"; my $ret; my $dosplit = $linepos < length($string); $string .= "\n" unless $string =~ /\n$/; if ($dosplit) { $ret = substr( $string, 0, $linepos ) . $ptr . substr( $string, $linepos ); } else { $ret = $string . $ptr; } return $ret; } } sub xml_escape { my $self = shift; my $text = shift; study $text; $text =~ s/\&/\&/g; $text =~ s/ 1; if ( $_ eq '>' ) { $text =~ s/>/\>/g; } elsif ( $_ eq '"' ) { $text =~ s/\"/\"/; } elsif ( $_ eq "'" ) { $text =~ s/\'/\'/; } else { my $rep = '&#' . sprintf( 'x%X', ord($_) ) . ';'; if (/\W/) { my $ptrn = "\\$_"; $text =~ s/$ptrn/$rep/g; } else { $text =~ s/$_/$rep/g; } } } $text; } sub skip_until { my $self = shift; if ( $self->{_State_} <= 1 ) { SkipUntil( $self->{Parser}, $_[0] ); } } sub release { my $self = shift; ParserRelease( $self->{Parser} ); } sub DESTROY { my $self = shift; ParserFree( $self->{Parser} ); } sub parse { my $self = shift; my $arg = shift; croak 'Parse already in progress (Expat)' if $self->{_State_}; $self->{_State_} = 1; my $parser = $self->{Parser}; my $ioref; my $result = 0; if ( defined $arg ) { local *@; if ( ref($arg) and UNIVERSAL::isa( $arg, 'IO::Handle' ) ) { $ioref = $arg; } elsif ( $] < 5.008 and defined tied($arg) ) { require IO::Handle; $ioref = $arg; } else { require IO::Handle; eval { no strict 'refs'; $ioref = *{$arg}{IO} if defined *{$arg}; }; if ( ref($ioref) eq 'FileHandle' ) { #for perl 5.10.x and possibly earlier, see t/file_open_scalar.t require FileHandle; } } } if ( defined($ioref) ) { my $delim = $self->{Stream_Delimiter}; my $prev_rs; my $ioclass = ref $ioref; $ioclass = 'IO::Handle' if !length $ioclass; $prev_rs = $ioclass->input_record_separator("\n$delim\n") if defined($delim); $result = ParseStream( $parser, $ioref, $delim ); $ioclass->input_record_separator($prev_rs) if defined($delim); } else { $result = ParseString( $parser, $arg ); } $self->{_State_} = 2; $result or croak $self->{ErrorMessage}; } sub parsestring { my $self = shift; $self->parse(@_); } sub parsefile { my $self = shift; croak 'Parser has already been used' if $self->{_State_}; open( my $fh, '<', $_[0] ) or croak "Couldn't open $_[0]:\n$!"; binmode($fh); my $ret = $self->parse($fh); close($fh); $ret; } ################################################################ package #hide from PAUSE XML::Parser::ContentModel; use overload '""' => \&asString, 'eq' => \&thiseq; sub EMPTY () { 1 } sub ANY () { 2 } sub MIXED () { 3 } sub NAME () { 4 } sub CHOICE () { 5 } sub SEQ () { 6 } sub isempty { return $_[0]->{Type} == EMPTY; } sub isany { return $_[0]->{Type} == ANY; } sub ismixed { return $_[0]->{Type} == MIXED; } sub isname { return $_[0]->{Type} == NAME; } sub name { return $_[0]->{Tag}; } sub ischoice { return $_[0]->{Type} == CHOICE; } sub isseq { return $_[0]->{Type} == SEQ; } sub quant { return $_[0]->{Quant}; } sub children { my $children = $_[0]->{Children}; if ( defined $children ) { return @$children; } return undef; } sub asString { my ($self) = @_; my $ret; if ( $self->{Type} == NAME ) { $ret = $self->{Tag}; } elsif ( $self->{Type} == EMPTY ) { return 'EMPTY'; } elsif ( $self->{Type} == ANY ) { return 'ANY'; } elsif ( $self->{Type} == MIXED ) { $ret = '(#PCDATA'; foreach ( @{ $self->{Children} } ) { $ret .= '|' . $_; } $ret .= ')'; } else { my $sep = $self->{Type} == CHOICE ? '|' : ','; $ret = '(' . join( $sep, map { $_->asString } @{ $self->{Children} } ) . ')'; } $ret .= $self->{Quant} if $self->{Quant}; return $ret; } sub thiseq { my $self = shift; return $self->asString eq $_[0]; } ################################################################ package #hide from PAUSE XML::Parser::ExpatNB; use Carp; our @ISA = qw(XML::Parser::Expat); sub parse { my $self = shift; my $class = ref($self); croak "parse method not supported in $class"; } sub parsestring { my $self = shift; my $class = ref($self); croak "parsestring method not supported in $class"; } sub parsefile { my $self = shift; my $class = ref($self); croak "parsefile method not supported in $class"; } sub parse_more { my ( $self, $data ) = @_; $self->{_State_} = 1; my $ret = XML::Parser::Expat::ParsePartial( $self->{Parser}, $data ); croak $self->{ErrorMessage} unless $ret; } sub parse_done { my $self = shift; my $ret = XML::Parser::Expat::ParseDone( $self->{Parser} ); unless ($ret) { my $msg = $self->{ErrorMessage}; $self->release; croak $msg; } $self->{_State_} = 2; my $result = $ret; my @result = (); my $final = $self->{FinalHandler}; if ( defined $final ) { if (wantarray) { @result = &$final($self); } else { $result = &$final($self); } } $self->release; return unless defined wantarray; return wantarray ? @result : $result; } ################################################################ package #hide from PAUSE XML::Parser::Encinfo; sub DESTROY { my $self = shift; XML::Parser::Expat::FreeEncoding($self); } 1; __END__ =head1 NAME XML::Parser::Expat - Lowlevel access to James Clark's expat XML parser =head1 SYNOPSIS use XML::Parser::Expat; $parser = XML::Parser::Expat->new; $parser->setHandlers('Start' => \&sh, 'End' => \&eh, 'Char' => \&ch); open(my $fh, '<', 'info.xml') or die "Couldn't open"; $parser->parse($fh); close($fh); # $parser->parse(' here we go '); sub sh { my ($p, $el, %atts) = @_; $p->setHandlers('Char' => \&spec) if ($el eq 'special'); ... } sub eh { my ($p, $el) = @_; $p->setHandlers('Char' => \&ch) # Special elements won't contain if ($el eq 'special'); # other special elements ... } =head1 DESCRIPTION This module provides an interface to James Clark's XML parser, expat. As in expat, a single instance of the parser can only parse one document. Calls to parsestring after the first for a given instance will die. Expat (and XML::Parser::Expat) are event based. As the parser recognizes parts of the document (say the start or end of an XML element), then any handlers registered for that type of an event are called with suitable parameters. =head1 METHODS =over 4 =item new This is a class method, the constructor for XML::Parser::Expat. Options are passed as keyword value pairs. The recognized options are: =over 4 =item * ProtocolEncoding The protocol encoding name. The default is none. The expat built-in encodings are: C, C, C, and C. Other encodings may be used if they have encoding maps in one of the directories in the @Encoding_Path list. Setting the protocol encoding overrides any encoding in the XML declaration. =item * Namespaces When this option is given with a true value, then the parser does namespace processing. By default, namespace processing is turned off. When it is turned on, the parser consumes I attributes and strips off prefixes from element and attributes names where those prefixes have a defined namespace. A name's namespace can be found using the L<"namespace"> method and two names can be checked for absolute equality with the L<"eq_name"> method. =item * NoExpand Normally, the parser will try to expand references to entities defined in the internal subset. If this option is set to a true value, and a default handler is also set, then the default handler will be called when an entity reference is seen in text. This has no effect if a default handler has not been registered, and it has no effect on the expansion of entity references inside attribute values. =item * Stream_Delimiter This option takes a string value. When this string is found alone on a line while parsing from a stream, then the parse is ended as if it saw an end of file. The intended use is with a stream of xml documents in a MIME multipart format. The string should not contain a trailing newline. =item * ErrorContext When this option is defined, errors are reported in context. The value of ErrorContext should be the number of lines to show on either side of the line in which the error occurred. =item * ParseParamEnt Unless standalone is set to "yes" in the XML declaration, setting this to a true value allows the external DTD to be read, and parameter entities to be parsed and expanded. =item * Base The base to use for relative pathnames or URLs. This can also be done by using the base method. =back =item setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]]) This method registers handlers for the various events. If no handlers are registered, then a call to parsestring or parsefile will only determine if the corresponding XML document is well formed (by returning without error.) This may be called from within a handler, after the parse has started. Setting a handler to something that evaluates to false unsets that handler. This method returns a list of type, handler pairs corresponding to the input. The handlers returned are the ones that were in effect before the call to setHandlers. The recognized events and the parameters passed to the corresponding handlers are: =over 4 =item * Start (Parser, Element [, Attr, Val [,...]]) This event is generated when an XML start tag is recognized. Parser is an XML::Parser::Expat instance. Element is the name of the XML element that is opened with the start tag. The Attr & Val pairs are generated for each attribute in the start tag. =item * End (Parser, Element) This event is generated when an XML end tag is recognized. Note that an XML empty tag () generates both a start and an end event. There is always a lower level start and end handler installed that wrap the corresponding callbacks. This is to handle the context mechanism. A consequence of this is that the default handler (see below) will not see a start tag or end tag unless the default_current method is called. =item * Char (Parser, String) This event is generated when non-markup is recognized. The non-markup sequence of characters is in String. A single non-markup sequence of characters may generate multiple calls to this handler. Whatever the encoding of the string in the original document, this is given to the handler in UTF-8. =item * Proc (Parser, Target, Data) This event is generated when a processing instruction is recognized. =item * Comment (Parser, String) This event is generated when a comment is recognized. =item * CdataStart (Parser) This is called at the start of a CDATA section. =item * CdataEnd (Parser) This is called at the end of a CDATA section. =item * Default (Parser, String) This is called for any characters that don't have a registered handler. This includes both characters that are part of markup for which no events are generated (markup declarations) and characters that could generate events, but for which no handler has been registered. Whatever the encoding in the original document, the string is returned to the handler in UTF-8. =item * Unparsed (Parser, Entity, Base, Sysid, Pubid, Notation) This is called for a declaration of an unparsed entity. Entity is the name of the entity. Base is the base to be used for resolving a relative URI. Sysid is the system id. Pubid is the public id. Notation is the notation name. Base and Pubid may be undefined. =item * Notation (Parser, Notation, Base, Sysid, Pubid) This is called for a declaration of notation. Notation is the notation name. Base is the base to be used for resolving a relative URI. Sysid is the system id. Pubid is the public id. Base, Sysid, and Pubid may all be undefined. =item * ExternEnt (Parser, Base, Sysid, Pubid) This is called when an external entity is referenced. Base is the base to be used for resolving a relative URI. Sysid is the system id. Pubid is the public id. Base, and Pubid may be undefined. This handler should either return a string, which represents the contents of the external entity, or return an open filehandle that can be read to obtain the contents of the external entity, or return undef, which indicates the external entity couldn't be found and will generate a parse error. If an open filehandle is returned, it must be returned as either a glob (*FOO) or as a reference to a glob (e.g. an instance of IO::Handle). =item * ExternEntFin (Parser) This is called after an external entity has been parsed. It allows applications to perform cleanup on actions performed in the above ExternEnt handler. =item * Entity (Parser, Name, Val, Sysid, Pubid, Ndata, IsParam) This is called when an entity is declared. For internal entities, the Val parameter will contain the value and the remaining three parameters will be undefined. For external entities, the Val parameter will be undefined, the Sysid parameter will have the system id, the Pubid parameter will have the public id if it was provided (it will be undefined otherwise), the Ndata parameter will contain the notation for unparsed entities. If this is a parameter entity declaration, then the IsParam parameter is true. Note that this handler and the Unparsed handler above overlap. If both are set, then this handler will not be called for unparsed entities. =item * Element (Parser, Name, Model) The element handler is called when an element declaration is found. Name is the element name, and Model is the content model as an XML::Parser::ContentModel object. See L<"XML::Parser::ContentModel Methods"> for methods available for this class. =item * Attlist (Parser, Elname, Attname, Type, Default, Fixed) This handler is called for each attribute in an ATTLIST declaration. So an ATTLIST declaration that has multiple attributes will generate multiple calls to this handler. The Elname parameter is the name of the element with which the attribute is being associated. The Attname parameter is the name of the attribute. Type is the attribute type, given as a string. Default is the default value, which will either be "#REQUIRED", "#IMPLIED" or a quoted string (i.e. the returned string will begin and end with a quote character). If Fixed is true, then this is a fixed attribute. =item * Doctype (Parser, Name, Sysid, Pubid, Internal) This handler is called for DOCTYPE declarations. Name is the document type name. Sysid is the system id of the document type, if it was provided, otherwise it's undefined. Pubid is the public id of the document type, which will be undefined if no public id was given. Internal will be true or false, indicating whether or not the doctype declaration contains an internal subset. =item * DoctypeFin (Parser) This handler is called after parsing of the DOCTYPE declaration has finished, including any internal or external DTD declarations. =item * XMLDecl (Parser, Version, Encoding, Standalone) This handler is called for XML declarations. Version is a string containing the version. Encoding is either undefined or contains an encoding string. Standalone is either undefined, or true or false. Undefined indicates that no standalone parameter was given in the XML declaration. True or false indicates "yes" or "no" respectively. =back =item namespace(name) Return the URI of the namespace that the name belongs to. If the name doesn't belong to any namespace, an undef is returned. This is only valid on names received through the Start or End handlers from a single document, or through a call to the generate_ns_name method. In other words, don't use names generated from one instance of XML::Parser::Expat with other instances. =item eq_name(name1, name2) Return true if name1 and name2 are identical (i.e. same name and from the same namespace.) This is only meaningful if both names were obtained through the Start or End handlers from a single document, or through a call to the generate_ns_name method. =item generate_ns_name(name, namespace) Return a name, associated with a given namespace, good for using with the above 2 methods. The namespace argument should be the namespace URI, not a prefix. =item new_ns_prefixes When called from a start tag handler, returns namespace prefixes declared with this start tag. If called elsewhere (or if there were no namespace prefixes declared), it returns an empty list. Setting of the default namespace is indicated with '#default' as a prefix. =item expand_ns_prefix(prefix) Return the uri to which the given prefix is currently bound. Returns undef if the prefix isn't currently bound. Use '#default' to find the current binding of the default namespace (if any). =item current_ns_prefixes Return a list of currently bound namespace prefixes. The order of the the prefixes in the list has no meaning. If the default namespace is currently bound, '#default' appears in the list. =item recognized_string Returns the string from the document that was recognized in order to call the current handler. For instance, when called from a start handler, it will give us the start-tag string. The string is encoded in UTF-8. This method doesn't return a meaningful string inside declaration handlers. =item original_string Returns the verbatim string from the document that was recognized in order to call the current handler. The string is in the original document encoding. This method doesn't return a meaningful string inside declaration handlers. =item default_current When called from a handler, causes the sequence of characters that generated the corresponding event to be sent to the default handler (if one is registered). Use of this method is deprecated in favor the recognized_string method, which you can use without installing a default handler. This method doesn't deliver a meaningful string to the default handler when called from inside declaration handlers. =item xpcroak(message) Concatenate onto the given message the current line number within the XML document plus the message implied by ErrorContext. Then croak with the formed message. =item xpcarp(message) Concatenate onto the given message the current line number within the XML document plus the message implied by ErrorContext. Then carp with the formed message. =item current_line Returns the line number of the current position of the parse. =item current_column Returns the column number of the current position of the parse. =item current_byte Returns the current position of the parse. =item base([NEWBASE]); Returns the current value of the base for resolving relative URIs. If NEWBASE is supplied, changes the base to that value. =item context Returns a list of element names that represent open elements, with the last one being the innermost. Inside start and end tag handlers, this will be the tag of the parent element. =item current_element Returns the name of the innermost currently opened element. Inside start or end handlers, returns the parent of the element associated with those tags. =item in_element(NAME) Returns true if NAME is equal to the name of the innermost currently opened element. If namespace processing is being used and you want to check against a name that may be in a namespace, then use the generate_ns_name method to create the NAME argument. =item within_element(NAME) Returns the number of times the given name appears in the context list. If namespace processing is being used and you want to check against a name that may be in a namespace, then use the generate_ns_name method to create the NAME argument. =item depth Returns the size of the context list. =item element_index Returns an integer that is the depth-first visit order of the current element. This will be zero outside of the root element. For example, this will return 1 when called from the start handler for the root element start tag. =item skip_until(INDEX) INDEX is an integer that represents an element index. When this method is called, all handlers are suspended until the start tag for an element that has an index number equal to INDEX is seen. If a start handler has been set, then this is the first tag that the start handler will see after skip_until has been called. =item position_in_context(LINES) Returns a string that shows the current parse position. LINES should be an integer >= 0 that represents the number of lines on either side of the current parse line to place into the returned string. =item xml_escape(TEXT [, CHAR [, CHAR ...]]) Returns TEXT with markup characters turned into character entities. Any additional characters provided as arguments are also turned into character references where found in TEXT. =item parse (SOURCE) The SOURCE parameter should either be a string containing the whole XML document, or it should be an open IO::Handle. Only a single document may be parsed for a given instance of XML::Parser::Expat, so this will croak if it's been called previously for this instance. =item parsestring(XML_DOC_STRING) Parses the given string as an XML document. Only a single document may be parsed for a given instance of XML::Parser::Expat, so this will die if either parsestring or parsefile has been called for this instance previously. This method is deprecated in favor of the parse method. =item parsefile(FILENAME) Parses the XML document in the given file. Will die if parsestring or parsefile has been called previously for this instance. =item is_defaulted(ATTNAME) NO LONGER WORKS. To find out if an attribute is defaulted please use the specified_attr method. =item specified_attr When the start handler receives lists of attributes and values, the non-defaulted (i.e. explicitly specified) attributes occur in the list first. This method returns the number of specified items in the list. So if this number is equal to the length of the list, there were no defaulted values. Otherwise the number points to the index of the first defaulted attribute name. =item finish Unsets all handlers (including internal ones that set context), but expat continues parsing to the end of the document or until it finds an error. It should finish up a lot faster than with the handlers set. =item release There are data structures used by XML::Parser::Expat that have circular references. This means that these structures will never be garbage collected unless these references are explicitly broken. Calling this method breaks those references (and makes the instance unusable.) Normally, higher level calls handle this for you, but if you are using XML::Parser::Expat directly, then it's your responsibility to call it. =back =head2 XML::Parser::ContentModel Methods The element declaration handlers are passed objects of this class as the content model of the element declaration. They also represent content particles, components of a content model. When referred to as a string, these objects are automagicly converted to a string representation of the model (or content particle). =over 4 =item isempty This method returns true if the object is "EMPTY", false otherwise. =item isany This method returns true if the object is "ANY", false otherwise. =item ismixed This method returns true if the object is "(#PCDATA)" or "(#PCDATA|...)*", false otherwise. =item isname This method returns if the object is an element name. =item ischoice This method returns true if the object is a choice of content particles. =item isseq This method returns true if the object is a sequence of content particles. =item quant This method returns undef or a string representing the quantifier ('?', '*', '+') associated with the model or particle. =item children This method returns undef or (for mixed, choice, and sequence types) an array of component content particles. There will always be at least one component for choices and sequences, but for a mixed content model of pure PCDATA, "(#PCDATA)", then an undef is returned. =back =head2 XML::Parser::ExpatNB Methods The class XML::Parser::ExpatNB is a subclass of XML::Parser::Expat used for non-blocking access to the expat library. It does not support the parse, parsestring, or parsefile methods, but it does have these additional methods: =over 4 =item parse_more(DATA) Feed expat more text to munch on. =item parse_done Tell expat that it's gotten the whole document. =back =head1 FUNCTIONS =over 4 =item XML::Parser::Expat::load_encoding(ENCODING) Load an external encoding. ENCODING is either the name of an encoding or the name of a file. The basename is converted to lowercase and a '.enc' extension is appended unless there's one already there. Then, unless it's an absolute pathname (i.e. begins with '/'), the first file by that name discovered in the @Encoding_Path path list is used. The encoding in the file is loaded and kept in the %Encoding_Table table. Earlier encodings of the same name are replaced. This function is automatically called by expat when it encounters an encoding it doesn't know about. Expat shouldn't call this twice for the same encoding name. The only reason users should use this function is to explicitly load an encoding not contained in the @Encoding_Path list. =back =head1 AUTHORS Larry Wall > wrote version 1.0. Clark Cooper > picked up support, changed the API for this version (2.x), provided documentation, and added some standard package features. =cut Style/Stream.pm000044400000007055152344545640007456 0ustar00# $Id: Stream.pm,v 1.1 2003-07-27 16:07:49 matt Exp $ package XML::Parser::Style::Stream; use strict; # This style invented by Tim Bray sub Init { no strict 'refs'; my $expat = shift; $expat->{Text} = ''; my $sub = $expat->{Pkg} . "::StartDocument"; &$sub($expat) if defined(&$sub); } sub Start { no strict 'refs'; my $expat = shift; my $type = shift; doText($expat); $_ = "<$type"; %_ = @_; while (@_) { $_ .= ' ' . shift() . '="' . shift() . '"'; } $_ .= '>'; my $sub = $expat->{Pkg} . "::StartTag"; if ( defined(&$sub) ) { &$sub( $expat, $type ); } else { print; } } sub End { no strict 'refs'; my $expat = shift; my $type = shift; # Set right context for Text handler push( @{ $expat->{Context} }, $type ); doText($expat); pop( @{ $expat->{Context} } ); $_ = ""; my $sub = $expat->{Pkg} . "::EndTag"; if ( defined(&$sub) ) { &$sub( $expat, $type ); } else { print; } } sub Char { my $expat = shift; $expat->{Text} .= shift; } sub Proc { no strict 'refs'; my $expat = shift; my $target = shift; my $text = shift; doText($expat); $_ = ""; my $sub = $expat->{Pkg} . "::PI"; if ( defined(&$sub) ) { &$sub( $expat, $target, $text ); } else { print; } } sub Final { no strict 'refs'; my $expat = shift; my $sub = $expat->{Pkg} . "::EndDocument"; &$sub($expat) if defined(&$sub); } sub doText { no strict 'refs'; my $expat = shift; $_ = $expat->{Text}; if ( length($_) ) { my $sub = $expat->{Pkg} . "::Text"; if ( defined(&$sub) ) { &$sub($expat); } else { print; } $expat->{Text} = ''; } } 1; __END__ =head1 NAME XML::Parser::Style::Stream - Stream style for XML::Parser =head1 SYNOPSIS use XML::Parser; my $p = XML::Parser->new(Style => 'Stream', Pkg => 'MySubs'); $p->parsefile('foo.xml'); { package MySubs; sub StartTag { my ($e, $name) = @_; # do something with start tags } sub EndTag { my ($e, $name) = @_; # do something with end tags } sub Characters { my ($e, $data) = @_; # do something with text nodes } } =head1 DESCRIPTION This style uses the Pkg option to find subs in a given package to call for each event. If none of the subs that this style looks for is there, then the effect of parsing with this style is to print a canonical copy of the document without comments or declarations. All the subs receive as their 1st parameter the Expat instance for the document they're parsing. It looks for the following routines: =over 4 =item * StartDocument Called at the start of the parse . =item * StartTag Called for every start tag with a second parameter of the element type. The $_ variable will contain a copy of the tag and the %_ variable will contain attribute values supplied for that element. =item * EndTag Called for every end tag with a second parameter of the element type. The $_ variable will contain a copy of the end tag. =item * Text Called just before start or end tags with accumulated non-markup text in the $_ variable. =item * PI Called for processing instructions. The $_ variable will contain a copy of the PI and the target and data are sent as 2nd and 3rd parameters respectively. =item * EndDocument Called at conclusion of the parse. =back =cut Style/Tree.pm000044400000004352152344545640007117 0ustar00# $Id: Tree.pm,v 1.2 2003-07-31 07:54:51 matt Exp $ package XML::Parser::Style::Tree; $XML::Parser::Built_In_Styles{Tree} = 1; sub Init { my $expat = shift; $expat->{Lists} = []; $expat->{Curlist} = $expat->{Tree} = []; } sub Start { my $expat = shift; my $tag = shift; my $newlist = [ {@_} ]; push @{ $expat->{Lists} }, $expat->{Curlist}; push @{ $expat->{Curlist} }, $tag => $newlist; $expat->{Curlist} = $newlist; } sub End { my $expat = shift; my $tag = shift; $expat->{Curlist} = pop @{ $expat->{Lists} }; } sub Char { my $expat = shift; my $text = shift; my $clist = $expat->{Curlist}; my $pos = $#$clist; if ( $pos > 0 and $clist->[ $pos - 1 ] eq '0' ) { $clist->[$pos] .= $text; } else { push @$clist, 0 => $text; } } sub Final { my $expat = shift; delete $expat->{Curlist}; delete $expat->{Lists}; $expat->{Tree}; } 1; __END__ =head1 NAME XML::Parser::Style::Tree - Tree style parser =head1 SYNOPSIS use XML::Parser; my $p = XML::Parser->new(Style => 'Tree'); my $tree = $p->parsefile('foo.xml'); =head1 DESCRIPTION This module implements XML::Parser's Tree style parser. When parsing a document, C will return a parse tree for the document. Each node in the tree takes the form of a tag, content pair. Text nodes are represented with a pseudo-tag of "0" and the string that is their content. For elements, the content is an array reference. The first item in the array is a (possibly empty) hash reference containing attributes. The remainder of the array is a sequence of tag-content pairs representing the content of the element. So for example the result of parsing: Hello thereHowdydo would be: Tag Content ================================================================== [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [ {}, 0, "Howdy", ref, [{}]], 0, "do" ] ] The root document "foo", has 3 children: a "head" element, a "bar" element and the text "do". After the empty attribute hash, these are represented in it's contents by 3 tag-content pairs. =cut Style/Subs.pm000044400000002177152344545640007137 0ustar00# $Id: Subs.pm,v 1.1 2003-07-27 16:07:49 matt Exp $ package XML::Parser::Style::Subs; sub Start { no strict 'refs'; my $expat = shift; my $tag = shift; my $sub = $expat->{Pkg} . "::$tag"; eval { &$sub( $expat, $tag, @_ ) }; } sub End { no strict 'refs'; my $expat = shift; my $tag = shift; my $sub = $expat->{Pkg} . "::${tag}_"; eval { &$sub( $expat, $tag ) }; } 1; __END__ =head1 NAME XML::Parser::Style::Subs - glue for handling element callbacks =head1 SYNOPSIS use XML::Parser; my $p = XML::Parser->new(Style => 'Subs', Pkg => 'MySubs'); $p->parsefile('foo.xml'); { package MySubs; sub foo { # start of foo tag } sub foo_ { # end of foo tag } } =head1 DESCRIPTION Each time an element starts, a sub by that name in the package specified by the Pkg option is called with the same parameters that the Start handler gets called with. Each time an element ends, a sub with that name appended with an underscore ("_"), is called with the same parameters that the End handler gets called with. Nothing special is returned by parse. =cut Style/Objects.pm000044400000003512152344545640007606 0ustar00# $Id: Objects.pm,v 1.1 2003-08-18 20:20:51 matt Exp $ package XML::Parser::Style::Objects; use strict; sub Init { my $expat = shift; $expat->{Lists} = []; $expat->{Curlist} = $expat->{Tree} = []; } sub Start { my $expat = shift; my $tag = shift; my $newlist = []; my $class = "${$expat}{Pkg}::$tag"; my $newobj = bless { @_, Kids => $newlist }, $class; push @{ $expat->{Lists} }, $expat->{Curlist}; push @{ $expat->{Curlist} }, $newobj; $expat->{Curlist} = $newlist; } sub End { my $expat = shift; my $tag = shift; $expat->{Curlist} = pop @{ $expat->{Lists} }; } sub Char { my $expat = shift; my $text = shift; my $class = "${$expat}{Pkg}::Characters"; my $clist = $expat->{Curlist}; my $pos = $#$clist; if ( $pos >= 0 and ref( $clist->[$pos] ) eq $class ) { $clist->[$pos]->{Text} .= $text; } else { push @$clist, bless { Text => $text }, $class; } } sub Final { my $expat = shift; delete $expat->{Curlist}; delete $expat->{Lists}; $expat->{Tree}; } 1; __END__ =head1 NAME XML::Parser::Style::Objects - Objects styler parser =head1 SYNOPSIS use XML::Parser; my $p = XML::Parser->new(Style => 'Objects', Pkg => 'MyNode'); my $tree = $p->parsefile('foo.xml'); =head1 DESCRIPTION This module implements XML::Parser's Objects style parser. This is similar to the Tree style, except that a hash object is created for each element. The corresponding object will be in the class whose name is created by appending "::" and the element name to the package set with the Pkg option. Non-markup text will be in the ::Characters class. The contents of the corresponding object will be in an anonymous array that is the value of the Kids property for that object. =head1 SEE ALSO L =cut Style/Debug.pm000044400000002004152344545640007236 0ustar00# $Id: Debug.pm,v 1.1 2003-07-27 16:07:49 matt Exp $ package XML::Parser::Style::Debug; use strict; sub Start { my $expat = shift; my $tag = shift; print STDERR "@{$expat->{Context}} \\\\ (@_)\n"; } sub End { my $expat = shift; my $tag = shift; print STDERR "@{$expat->{Context}} //\n"; } sub Char { my $expat = shift; my $text = shift; $text =~ s/([\x80-\xff])/sprintf "#x%X;", ord $1/eg; $text =~ s/([\t\n])/sprintf "#%d;", ord $1/eg; print STDERR "@{$expat->{Context}} || $text\n"; } sub Proc { my $expat = shift; my $target = shift; my $text = shift; my @foo = @{ $expat->{Context} }; print STDERR "@foo $target($text)\n"; } 1; __END__ =head1 NAME XML::Parser::Style::Debug - Debug style for XML::Parser =head1 SYNOPSIS use XML::Parser; my $p = XML::Parser->new(Style => 'Debug'); $p->parsefile('foo.xml'); =head1 DESCRIPTION This just prints out the document in outline form to STDERR. Nothing special is returned by parse. =cut LWPExternEnt.pl000044400000003056152344545640007416 0ustar00# LWPExternEnt.pl # # Copyright (c) 2000 Clark Cooper # All rights reserved. # # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. package XML::Parser; use URI; use URI::file; use LWP::UserAgent; ## ## Note that this external entity handler reads the entire entity into ## memory, so it will choke on huge ones. It would be really nice if ## LWP::UserAgent optionally returned us an IO::Handle. ## sub lwp_ext_ent_handler { my ($xp, $base, $sys) = @_; # We don't use public id my $uri; if (defined $base) { # Base may have been set by parsefile, which is agnostic about # whether its a file or URI. my $base_uri = new URI($base); unless (defined $base_uri->scheme) { $base_uri = URI->new_abs($base_uri, URI::file->cwd); } $uri = URI->new_abs($sys, $base_uri); } else { $uri = new URI($sys); unless (defined $uri->scheme) { $uri = URI->new_abs($uri, URI::file->cwd); } } my $ua = $xp->{_lwpagent}; unless (defined $ua) { $ua = $xp->{_lwpagent} = new LWP::UserAgent(); $ua->env_proxy(); } my $req = new HTTP::Request('GET', $uri); my $res = $ua->request($req); if ($res->is_error) { $xp->{ErrorMessage} .= "\n" . $res->status_line . " $uri"; return undef; } $xp->{_BaseStack} ||= []; push(@{$xp->{_BaseStack}}, $base); $xp->base($uri); return $res->content; } # End lwp_ext_ent_handler sub lwp_ext_ent_cleanup { my ($xp) = @_; $xp->base(pop(@{$xp->{_BaseStack}})); } # End lwp_ext_ent_cleanup 1; Result.pm000064400000014001152347644500006366 0ustar00package TAP::Parser::Result; use strict; use warnings; use base 'TAP::Object'; BEGIN { # make is_* methods my @attrs = qw( plan pragma test comment bailout version unknown yaml ); no strict 'refs'; for my $token (@attrs) { my $method = "is_$token"; *$method = sub { return $token eq shift->type }; } } ############################################################################## =head1 NAME TAP::Parser::Result - Base class for TAP::Parser output objects =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS # abstract class - not meant to be used directly # see TAP::Parser::ResultFactory for preferred usage # directly: use TAP::Parser::Result; my $token = {...}; my $result = TAP::Parser::Result->new( $token ); =head2 DESCRIPTION This is a simple base class used by L to store objects that represent the current bit of test output data from TAP (usually a single line). Unless you're subclassing, you probably won't need to use this module directly. =head2 METHODS =head3 C # see TAP::Parser::ResultFactory for preferred usage # to use directly: my $result = TAP::Parser::Result->new($token); Returns an instance the appropriate class for the test token passed in. =cut # new() implementation provided by TAP::Object sub _initialize { my ( $self, $token ) = @_; if ($token) { # assign to a hash slice to make a shallow copy of the token. # I guess we could assign to the hash as (by default) there are not # contents, but that seems less helpful if someone wants to subclass us @{$self}{ keys %$token } = values %$token; } return $self; } ############################################################################## =head2 Boolean methods The following methods all return a boolean value and are to be overridden in the appropriate subclass. =over 4 =item * C Indicates whether or not this is the test plan line. 1..3 =item * C Indicates whether or not this is a pragma line. pragma +strict =item * C Indicates whether or not this is a test line. ok 1 Is OK! =item * C Indicates whether or not this is a comment. # this is a comment =item * C Indicates whether or not this is bailout line. Bail out! We're out of dilithium crystals. =item * C Indicates whether or not this is a TAP version line. TAP version 4 =item * C Indicates whether or not the current line could be parsed. ... this line is junk ... =item * C Indicates whether or not this is a YAML chunk. =back =cut ############################################################################## =head3 C print $result->raw; Returns the original line of text which was parsed. =cut sub raw { shift->{raw} } ############################################################################## =head3 C my $type = $result->type; Returns the "type" of a token, such as C or C. =cut sub type { shift->{type} } ############################################################################## =head3 C print $result->as_string; Prints a string representation of the token. This might not be the exact output, however. Tests will have test numbers added if not present, TODO and SKIP directives will be capitalized and, in general, things will be cleaned up. If you need the original text for the token, see the C method. =cut sub as_string { shift->{raw} } ############################################################################## =head3 C if ( $result->is_ok ) { ... } Reports whether or not a given result has passed. Anything which is B a test result returns true. This is merely provided as a convenient shortcut. =cut sub is_ok {1} ############################################################################## =head3 C Deprecated. Please use C instead. =cut sub passed { warn 'passed() is deprecated. Please use "is_ok()"'; shift->is_ok; } ############################################################################## =head3 C if ( $result->has_directive ) { ... } Indicates whether or not the given result has a TODO or SKIP directive. =cut sub has_directive { my $self = shift; return ( $self->has_todo || $self->has_skip ); } ############################################################################## =head3 C if ( $result->has_todo ) { ... } Indicates whether or not the given result has a TODO directive. =cut sub has_todo { 'TODO' eq ( shift->{directive} || '' ) } ############################################################################## =head3 C if ( $result->has_skip ) { ... } Indicates whether or not the given result has a SKIP directive. =cut sub has_skip { 'SKIP' eq ( shift->{directive} || '' ) } =head3 C Set the directive associated with this token. Used internally to fake TODO tests. =cut sub set_directive { my ( $self, $dir ) = @_; $self->{directive} = $dir; } 1; =head1 SUBCLASSING Please see L for a subclassing overview. Remember: if you want your subclass to be automatically used by the parser, you'll have to register it with L. If you're creating a completely new result I, you'll probably need to subclass L too, or else it'll never get used. =head2 Example package MyResult; use strict; use base 'TAP::Parser::Result'; # register with the factory: TAP::Parser::ResultFactory->register_type( 'my_type' => __PACKAGE__ ); sub as_string { 'My results all look the same' } =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, =cut Scheduler/Spinner.pm000064400000001736152347644500010457 0ustar00package TAP::Parser::Scheduler::Spinner; use strict; use warnings; use Carp; =head1 NAME TAP::Parser::Scheduler::Spinner - A no-op job. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Scheduler::Spinner; =head1 DESCRIPTION A no-op job. Returned by C as an instruction to the harness to spin (keep executing tests) while the scheduler can't return a real job. =head1 METHODS =head2 Class Methods =head3 C my $job = TAP::Parser::Scheduler::Spinner->new; Ignores any arguments and returns a new C object. =cut sub new { bless {}, shift } =head2 Instance Methods =head3 C Returns true indicating that is a 'spinner' job. Spinners are returned when the scheduler still has pending jobs but can't (because of locking) return one right now. =cut sub is_spinner {1} =head1 SEE ALSO L, L =cut 1; Scheduler/Job.pm000064400000004231152347644500007544 0ustar00package TAP::Parser::Scheduler::Job; use strict; use warnings; use Carp; =head1 NAME TAP::Parser::Scheduler::Job - A single testing job. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Scheduler::Job; =head1 DESCRIPTION Represents a single test 'job'. =head1 METHODS =head2 Class Methods =head3 C my $job = TAP::Parser::Scheduler::Job->new( $filename, $description ); Given the filename and description of a test as scalars, returns a new L object. =cut sub new { my ( $class, $name, $desc, @ctx ) = @_; return bless { filename => $name, description => $desc, @ctx ? ( context => \@ctx ) : (), }, $class; } =head2 Instance Methods =head3 C $self->on_finish(\&method). Register a closure to be called when this job is destroyed. The callback will be passed the C object as it's only argument. =cut sub on_finish { my ( $self, $cb ) = @_; $self->{on_finish} = $cb; } =head3 C $self->finish; Called when a job is complete to unlock it. If a callback has been registered with C, it calls it. Otherwise, it does nothing. =cut sub finish { my $self = shift; if ( my $cb = $self->{on_finish} ) { $cb->($self); } } =head2 Attributes $self->filename; $self->description; $self->context; These are all "getters" which return the data set for these attributes during object construction. =head3 C =head3 C =head3 C =cut sub filename { shift->{filename} } sub description { shift->{description} } sub context { @{ shift->{context} || [] } } =head3 C For backwards compatibility in callbacks. =cut sub as_array_ref { my $self = shift; return [ $self->filename, $self->description, $self->{context} ||= [] ]; } =head3 C $self->is_spinner; Returns false indicating that this is a real job rather than a 'spinner'. Spinners are returned when the scheduler still has pending jobs but can't (because of locking) return one right now. =cut sub is_spinner {0} 1; Source.pm000064400000022517152347644500006363 0ustar00package TAP::Parser::Source; use strict; use warnings; use File::Basename qw( fileparse ); use base 'TAP::Object'; use constant BLK_SIZE => 512; =head1 NAME TAP::Parser::Source - a TAP source & meta data about it =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; my $source = TAP::Parser::Source->new; $source->raw( \'reference to raw TAP source' ) ->config( \%config ) ->merge( $boolean ) ->switches( \@switches ) ->test_args( \@args ) ->assemble_meta; do { ... } if $source->meta->{is_file}; # see assemble_meta for a full list of data available =head1 DESCRIPTION A TAP I is something that produces a stream of TAP for the parser to consume, such as an executable file, a text file, an archive, an IO handle, a database, etc. Cs encapsulate these I sources, and provide some useful meta data about them. They are used by Ls, which do whatever is required to produce & capture a stream of TAP from the I source, and package it up in a L for the parser to consume. Unless you're writing a new L, a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $source = TAP::Parser::Source->new; Returns a new C object. =cut # new() implementation supplied by TAP::Object sub _initialize { my ($self) = @_; $self->meta( {} ); $self->config( {} ); return $self; } ############################################################################## =head2 Instance Methods =head3 C my $raw = $source->raw; $source->raw( $some_value ); Chaining getter/setter for the raw TAP source. This is a reference, as it may contain large amounts of data (eg: raw TAP). =head3 C my $meta = $source->meta; $source->meta({ %some_value }); Chaining getter/setter for meta data about the source. This defaults to an empty hashref. See L for more info. =head3 C True if the source has meta data. =head3 C my $config = $source->config; $source->config({ %some_value }); Chaining getter/setter for the source's configuration, if any has been provided by the user. How it's used is up to you. This defaults to an empty hashref. See L for more info. =head3 C my $merge = $source->merge; $source->config( $bool ); Chaining getter/setter for the flag that dictates whether STDOUT and STDERR should be merged (where appropriate). Defaults to undef. =head3 C my $switches = $source->switches; $source->config([ @switches ]); Chaining getter/setter for the list of command-line switches that should be passed to the source (where appropriate). Defaults to undef. =head3 C my $test_args = $source->test_args; $source->config([ @test_args ]); Chaining getter/setter for the list of command-line arguments that should be passed to the source (where appropriate). Defaults to undef. =cut sub raw { my $self = shift; return $self->{raw} unless @_; $self->{raw} = shift; return $self; } sub meta { my $self = shift; return $self->{meta} unless @_; $self->{meta} = shift; return $self; } sub has_meta { return scalar %{ shift->meta } ? 1 : 0; } sub config { my $self = shift; return $self->{config} unless @_; $self->{config} = shift; return $self; } sub merge { my $self = shift; return $self->{merge} unless @_; $self->{merge} = shift; return $self; } sub switches { my $self = shift; return $self->{switches} unless @_; $self->{switches} = shift; return $self; } sub test_args { my $self = shift; return $self->{test_args} unless @_; $self->{test_args} = shift; return $self; } =head3 C my $meta = $source->assemble_meta; Gathers meta data about the L source, stashes it in L and returns it as a hashref. This is done so that the Ls don't have to repeat common checks. Currently this includes: is_scalar => $bool, is_hash => $bool, is_array => $bool, # for scalars: length => $n has_newlines => $bool # only done if the scalar looks like a filename is_file => $bool, is_dir => $bool, is_symlink => $bool, file => { # only done if the scalar looks like a filename basename => $string, # including ext dir => $string, ext => $string, lc_ext => $string, # system checks exists => $bool, stat => [ ... ], # perldoc -f stat empty => $bool, size => $n, text => $bool, binary => $bool, read => $bool, write => $bool, execute => $bool, setuid => $bool, setgid => $bool, sticky => $bool, is_file => $bool, is_dir => $bool, is_symlink => $bool, # only done if the file's a symlink lstat => [ ... ], # perldoc -f lstat # only done if the file's a readable text file shebang => $first_line, } # for arrays: size => $n, =cut sub assemble_meta { my ($self) = @_; return $self->meta if $self->has_meta; my $meta = $self->meta; my $raw = $self->raw; # rudimentary is object test - if it's blessed it'll # inherit from UNIVERSAL $meta->{is_object} = UNIVERSAL::isa( $raw, 'UNIVERSAL' ) ? 1 : 0; if ( $meta->{is_object} ) { $meta->{class} = ref($raw); } else { my $ref = lc( ref($raw) ); $meta->{"is_$ref"} = 1; } if ( $meta->{is_scalar} ) { my $source = $$raw; $meta->{length} = length($$raw); $meta->{has_newlines} = $$raw =~ /\n/ ? 1 : 0; # only do file checks if it looks like a filename if ( !$meta->{has_newlines} and $meta->{length} < 1024 ) { my $file = {}; $file->{exists} = -e $source ? 1 : 0; if ( $file->{exists} ) { $meta->{file} = $file; # avoid extra system calls (see `perldoc -f -X`) $file->{stat} = [ stat(_) ]; $file->{empty} = -z _ ? 1 : 0; $file->{size} = -s _; $file->{text} = -T _ ? 1 : 0; $file->{binary} = -B _ ? 1 : 0; $file->{read} = -r _ ? 1 : 0; $file->{write} = -w _ ? 1 : 0; $file->{execute} = -x _ ? 1 : 0; $file->{setuid} = -u _ ? 1 : 0; $file->{setgid} = -g _ ? 1 : 0; $file->{sticky} = -k _ ? 1 : 0; $meta->{is_file} = $file->{is_file} = -f _ ? 1 : 0; $meta->{is_dir} = $file->{is_dir} = -d _ ? 1 : 0; # symlink check requires another system call $meta->{is_symlink} = $file->{is_symlink} = -l $source ? 1 : 0; if ( $file->{is_symlink} ) { $file->{lstat} = [ lstat(_) ]; } # put together some common info about the file ( $file->{basename}, $file->{dir}, $file->{ext} ) = map { defined $_ ? $_ : '' } fileparse( $source, qr/\.[^.]*/ ); $file->{lc_ext} = lc( $file->{ext} ); $file->{basename} .= $file->{ext} if $file->{ext}; if ( !$file->{is_dir} && $file->{read} ) { eval { $file->{shebang} = $self->shebang($$raw); }; if ( my $e = $@ ) { warn $e; } } } } } elsif ( $meta->{is_array} ) { $meta->{size} = $#$raw + 1; } elsif ( $meta->{is_hash} ) { ; # do nothing } return $meta; } =head3 C Get the shebang line for a script file. my $shebang = TAP::Parser::Source->shebang( $some_script ); May be called as a class method =cut { # Global shebang cache. my %shebang_for; sub _read_shebang { my ( $class, $file ) = @_; open my $fh, '<', $file or die "Can't read $file: $!\n"; # Might be a binary file - so read a fixed number of bytes. my $got = read $fh, my ($buf), BLK_SIZE; defined $got or die "I/O error: $!\n"; return $1 if $buf =~ /(.*)/; return; } sub shebang { my ( $class, $file ) = @_; $shebang_for{$file} = $class->_read_shebang($file) unless exists $shebang_for{$file}; return $shebang_for{$file}; } } =head3 C my $config = $source->config_for( $class ); Returns L for the $class given. Class names may be fully qualified or abbreviated, eg: # these are equivalent $source->config_for( 'Perl' ); $source->config_for( 'TAP::Parser::SourceHandler::Perl' ); If a fully qualified $class is given, its abbreviated version is checked first. =cut sub config_for { my ( $self, $class ) = @_; my ($abbrv_class) = ( $class =~ /(?:\:\:)?(\w+)$/ ); my $config = $self->config->{$abbrv_class} || $self->config->{$class}; return $config; } 1; __END__ =head1 AUTHORS Steve Purkis. =head1 SEE ALSO L, L, L, L =cut SourceHandler/Perl.pm000064400000022347152347644500010564 0ustar00package TAP::Parser::SourceHandler::Perl; use strict; use warnings; use Config; use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ ); use constant IS_VMS => ( $^O eq 'VMS' ); use TAP::Parser::IteratorFactory (); use TAP::Parser::Iterator::Process (); use Text::ParseWords qw(shellwords); use base 'TAP::Parser::SourceHandler::Executable'; TAP::Parser::IteratorFactory->register_handler(__PACKAGE__); =head1 NAME TAP::Parser::SourceHandler::Perl - Stream TAP from a Perl executable =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; use TAP::Parser::SourceHandler::Perl; my $source = TAP::Parser::Source->new->raw( \'script.pl' ); $source->assemble_meta; my $class = 'TAP::Parser::SourceHandler::Perl'; my $vote = $class->can_handle( $source ); my $iter = $class->make_iterator( $source ); =head1 DESCRIPTION This is a I L - it has 2 jobs: 1. Figure out if the L it's given is actually a Perl script (L). 2. Creates an iterator for Perl sources (L). Unless you're writing a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $vote = $class->can_handle( $source ); Only votes if $source looks like a file. Casts the following votes: 0.9 if it has a shebang ala "#!...perl" 0.75 if it has any shebang 0.8 if it's a .t file 0.9 if it's a .pl file 0.75 if it's in a 't' directory 0.25 by default (backwards compat) =cut sub can_handle { my ( $class, $source ) = @_; my $meta = $source->meta; return 0 unless $meta->{is_file}; my $file = $meta->{file}; if ( my $shebang = $file->{shebang} ) { return 0.9 if $shebang =~ /^#!.*\bperl/; # We favour Perl as the interpreter for any shebang to preserve # previous semantics: we used to execute everything via Perl and # relied on it to pass the shebang off to the appropriate # interpreter. return 0.3; } return 0.8 if $file->{lc_ext} eq '.t'; # vote higher than Executable return 0.9 if $file->{lc_ext} eq '.pl'; return 0.75 if $file->{dir} =~ /^t\b/; # vote higher than Executable # backwards compat, always vote: return 0.25; } =head3 C my $iterator = $class->make_iterator( $source ); Constructs & returns a new L for the source. Assumes C<$source-Eraw> contains a reference to the perl script. Cs if the file could not be found. The command to run is built as follows: $perl @switches $perl_script @test_args The perl command to use is determined by L. The command generated is guaranteed to preserve: PERL5LIB PERL5OPT Taint Mode, if set in the script's shebang I the command generated will I respect any shebang line defined in your Perl script. This is only a problem if you have compiled a custom version of Perl or if you want to use a specific version of Perl for one test and a different version for another, for example: #!/path/to/a/custom_perl --some --args #!/usr/local/perl-5.6/bin/perl -w Currently you need to write a plugin to get around this. =cut sub _autoflush_stdhandles { my ($class) = @_; $class->_autoflush( \*STDOUT ); $class->_autoflush( \*STDERR ); } sub make_iterator { my ( $class, $source ) = @_; my $meta = $source->meta; my $perl_script = ${ $source->raw }; $class->_croak("Cannot find ($perl_script)") unless $meta->{is_file}; # TODO: does this really need to be done here? $class->_autoflush_stdhandles; my ( $libs, $switches ) = $class->_mangle_switches( $class->_filter_libs( $class->_switches($source) ) ); $class->_run( $source, $libs, $switches ); } sub _has_taint_switch { my( $class, $switches ) = @_; my $has_taint = grep { $_ eq "-T" || $_ eq "-t" } @{$switches}; return $has_taint ? 1 : 0; } sub _mangle_switches { my ( $class, $libs, $switches ) = @_; # Taint mode ignores environment variables so we must retranslate # PERL5LIB as -I switches and place PERL5OPT on the command line # in order that it be seen. if ( $class->_has_taint_switch($switches) ) { my @perl5lib = defined $ENV{PERL5LIB} ? split /$Config{path_sep}/, $ENV{PERL5LIB} : (); return ( $libs, [ @{$switches}, $class->_libs2switches([@$libs, @perl5lib]), defined $ENV{PERL5OPT} ? shellwords( $ENV{PERL5OPT} ) : () ], ); } return ( $libs, $switches ); } sub _filter_libs { my ( $class, @switches ) = @_; my $path_sep = $Config{path_sep}; my $path_re = qr{$path_sep}; # Filter out any -I switches to be handled as libs later. # # Nasty kludge. It might be nicer if we got the libs separately # although at least this way we find any -I switches that were # supplied other then as explicit libs. # # We filter out any names containing colons because they will break # PERL5LIB my @libs; my @filtered_switches; for (@switches) { if ( !/$path_re/ && m/ ^ ['"]? -I ['"]? (.*?) ['"]? $ /x ) { push @libs, $1; } else { push @filtered_switches, $_; } } return \@libs, \@filtered_switches; } sub _iterator_hooks { my ( $class, $source, $libs, $switches ) = @_; my $setup = sub { if ( @{$libs} and !$class->_has_taint_switch($switches) ) { $ENV{PERL5LIB} = join( $Config{path_sep}, grep {defined} @{$libs}, $ENV{PERL5LIB} ); } }; # VMS environment variables aren't guaranteed to reset at the end of # the process, so we need to put PERL5LIB back. my $previous = $ENV{PERL5LIB}; my $teardown = sub { if ( defined $previous ) { $ENV{PERL5LIB} = $previous; } else { delete $ENV{PERL5LIB}; } }; return ( $setup, $teardown ); } sub _run { my ( $class, $source, $libs, $switches ) = @_; my @command = $class->_get_command_for_switches( $source, $switches ) or $class->_croak("No command found!"); my ( $setup, $teardown ) = $class->_iterator_hooks( $source, $libs, $switches ); return $class->_create_iterator( $source, \@command, $setup, $teardown ); } sub _create_iterator { my ( $class, $source, $command, $setup, $teardown ) = @_; return TAP::Parser::Iterator::Process->new( { command => $command, merge => $source->merge, setup => $setup, teardown => $teardown, } ); } sub _get_command_for_switches { my ( $class, $source, $switches ) = @_; my $file = ${ $source->raw }; my @args = @{ $source->test_args || [] }; my $command = $class->get_perl; # XXX don't need to quote if we treat the parts as atoms (except maybe vms) #$file = qq["$file"] if ( $file =~ /\s/ ) && ( $file !~ /^".*"$/ ); my @command = ( $command, @{$switches}, $file, @args ); return @command; } sub _libs2switches { my $class = shift; return map {"-I$_"} grep {$_} @{ $_[0] }; } =head3 C Decode any taint switches from a Perl shebang line. # $taint will be 't' my $taint = TAP::Parser::SourceHandler::Perl->get_taint( '#!/usr/bin/perl -t' ); # $untaint will be undefined my $untaint = TAP::Parser::SourceHandler::Perl->get_taint( '#!/usr/bin/perl' ); =cut sub get_taint { my ( $class, $shebang ) = @_; return unless defined $shebang && $shebang =~ /^#!.*\bperl.*\s-\w*([Tt]+)/; return $1; } sub _switches { my ( $class, $source ) = @_; my $file = ${ $source->raw }; my @switches = @{ $source->switches || [] }; my $shebang = $source->meta->{file}->{shebang}; return unless defined $shebang; my $taint = $class->get_taint($shebang); push @switches, "-$taint" if defined $taint; # Quote the argument if we're VMS, since VMS will downcase anything # not quoted. if (IS_VMS) { for (@switches) { $_ = qq["$_"]; } } return @switches; } =head3 C Gets the version of Perl currently running the test suite. =cut sub get_perl { my $class = shift; return $ENV{HARNESS_PERL} if defined $ENV{HARNESS_PERL}; return qq["$^X"] if IS_WIN32 && ( $^X =~ /[^\w\.\/\\]/ ); return $^X; } 1; __END__ =head1 SUBCLASSING Please see L for a subclassing overview. =head2 Example package MyPerlSourceHandler; use strict; use TAP::Parser::SourceHandler::Perl; use base 'TAP::Parser::SourceHandler::Perl'; # use the version of perl from the shebang line in the test file sub get_perl { my $self = shift; if (my $shebang = $self->shebang( $self->{file} )) { $shebang =~ /^#!(.*\bperl.*?)(?:(?:\s)|(?:$))/; return $1 if $1; } return $self->SUPER::get_perl(@_); } =head1 SEE ALSO L, L, L, L, L, L, L, L =cut SourceHandler/RawTAP.pm000064400000005432152347644500010754 0ustar00package TAP::Parser::SourceHandler::RawTAP; use strict; use warnings; use TAP::Parser::IteratorFactory (); use TAP::Parser::Iterator::Array (); use base 'TAP::Parser::SourceHandler'; TAP::Parser::IteratorFactory->register_handler(__PACKAGE__); =head1 NAME TAP::Parser::SourceHandler::RawTAP - Stream output from raw TAP in a scalar/array ref. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; use TAP::Parser::SourceHandler::RawTAP; my $source = TAP::Parser::Source->new->raw( \"1..1\nok 1\n" ); $source->assemble_meta; my $class = 'TAP::Parser::SourceHandler::RawTAP'; my $vote = $class->can_handle( $source ); my $iter = $class->make_iterator( $source ); =head1 DESCRIPTION This is a I L - it has 2 jobs: 1. Figure out if the L it's given is raw TAP output (L). 2. Creates an iterator for raw TAP output (L). Unless you're writing a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $vote = $class->can_handle( $source ); Only votes if $source is an array, or a scalar with newlines. Casts the following votes: 0.9 if it's a scalar with '..' in it 0.7 if it's a scalar with 'ok' in it 0.3 if it's just a scalar with newlines 0.5 if it's an array =cut sub can_handle { my ( $class, $src ) = @_; my $meta = $src->meta; return 0 if $meta->{file}; if ( $meta->{is_scalar} ) { return 0 unless $meta->{has_newlines}; return 0.9 if ${ $src->raw } =~ /\d\.\.\d/; return 0.7 if ${ $src->raw } =~ /ok/; return 0.3; } elsif ( $meta->{is_array} ) { return 0.5; } return 0; } =head3 C my $iterator = $class->make_iterator( $source ); Returns a new L for the source. C<$source-Eraw> must be an array ref, or a scalar ref. Cs on error. =cut sub make_iterator { my ( $class, $src ) = @_; my $meta = $src->meta; my $tap_array; if ( $meta->{is_scalar} ) { $tap_array = [ split "\n" => ${ $src->raw } ]; } elsif ( $meta->{is_array} ) { $tap_array = $src->raw; } $class->_croak('No raw TAP found in $source->raw') unless scalar $tap_array; return TAP::Parser::Iterator::Array->new($tap_array); } 1; =head1 SUBCLASSING Please see L for a subclassing overview. =head1 SEE ALSO L, L, L, L, L, L, L, L =cut SourceHandler/Handle.pm000064400000005133152347644500011047 0ustar00package TAP::Parser::SourceHandler::Handle; use strict; use warnings; use TAP::Parser::IteratorFactory (); use TAP::Parser::Iterator::Stream (); use base 'TAP::Parser::SourceHandler'; TAP::Parser::IteratorFactory->register_handler(__PACKAGE__); =head1 NAME TAP::Parser::SourceHandler::Handle - Stream TAP from an IO::Handle or a GLOB. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; use TAP::Parser::SourceHandler::Executable; my $source = TAP::Parser::Source->new->raw( \*TAP_FILE ); $source->assemble_meta; my $class = 'TAP::Parser::SourceHandler::Handle'; my $vote = $class->can_handle( $source ); my $iter = $class->make_iterator( $source ); =head1 DESCRIPTION This is a I L class. It has 2 jobs: 1. Figure out if the L it's given is an L or GLOB containing raw TAP output (L). 2. Creates an iterator for IO::Handle's & globs (L). Unless you're writing a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $vote = $class->can_handle( $source ); Casts the following votes: 0.9 if $source is an IO::Handle 0.8 if $source is a glob =cut sub can_handle { my ( $class, $src ) = @_; my $meta = $src->meta; return 0.9 if $meta->{is_object} && UNIVERSAL::isa( $src->raw, 'IO::Handle' ); return 0.8 if $meta->{is_glob}; return 0; } =head3 C my $iterator = $class->make_iterator( $source ); Returns a new L for the source. =cut sub make_iterator { my ( $class, $source ) = @_; $class->_croak('$source->raw must be a glob ref or an IO::Handle') unless $source->meta->{is_glob} || UNIVERSAL::isa( $source->raw, 'IO::Handle' ); return $class->iterator_class->new( $source->raw ); } =head3 C The class of iterator to use, override if you're sub-classing. Defaults to L. =cut use constant iterator_class => 'TAP::Parser::Iterator::Stream'; 1; =head1 SUBCLASSING Please see L for a subclassing overview. =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L =cut SourceHandler/Executable.pm000064400000007715152347644500011745 0ustar00package TAP::Parser::SourceHandler::Executable; use strict; use warnings; use TAP::Parser::IteratorFactory (); use TAP::Parser::Iterator::Process (); use base 'TAP::Parser::SourceHandler'; TAP::Parser::IteratorFactory->register_handler(__PACKAGE__); =head1 NAME TAP::Parser::SourceHandler::Executable - Stream output from an executable TAP source =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; use TAP::Parser::SourceHandler::Executable; my $source = TAP::Parser::Source->new->raw(['/usr/bin/ruby', 'mytest.rb']); $source->assemble_meta; my $class = 'TAP::Parser::SourceHandler::Executable'; my $vote = $class->can_handle( $source ); my $iter = $class->make_iterator( $source ); =head1 DESCRIPTION This is an I L - it has 2 jobs: 1. Figure out if the L it's given is an executable command (L). 2. Creates an iterator for executable commands (L). Unless you're writing a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $vote = $class->can_handle( $source ); Only votes if $source looks like an executable file. Casts the following votes: 0.9 if it's a hash with an 'exec' key 0.8 if it's a .bat file 0.75 if it's got an execute bit set =cut sub can_handle { my ( $class, $src ) = @_; my $meta = $src->meta; if ( $meta->{is_file} ) { my $file = $meta->{file}; return 0.85 if $file->{execute} && $file->{binary}; return 0.8 if $file->{lc_ext} eq '.bat'; return 0.25 if $file->{execute}; } elsif ( $meta->{is_hash} ) { return 0.9 if $src->raw->{exec}; } return 0; } =head3 C my $iterator = $class->make_iterator( $source ); Returns a new L for the source. C<$source-Eraw> must be in one of the following forms: { exec => [ @exec ] } [ @exec ] $file Cs on error. =cut sub make_iterator { my ( $class, $source ) = @_; my $meta = $source->meta; my @command; if ( $meta->{is_hash} ) { @command = @{ $source->raw->{exec} || [] }; } elsif ( $meta->{is_scalar} ) { @command = ${ $source->raw }; } elsif ( $meta->{is_array} ) { @command = @{ $source->raw }; } $class->_croak('No command found in $source->raw!') unless @command; $class->_autoflush( \*STDOUT ); $class->_autoflush( \*STDERR ); push @command, @{ $source->test_args || [] }; return $class->iterator_class->new( { command => \@command, merge => $source->merge } ); } =head3 C The class of iterator to use, override if you're sub-classing. Defaults to L. =cut use constant iterator_class => 'TAP::Parser::Iterator::Process'; # Turns on autoflush for the handle passed sub _autoflush { my ( $class, $flushed ) = @_; my $old_fh = select $flushed; $| = 1; select $old_fh; } 1; =head1 SUBCLASSING Please see L for a subclassing overview. =head2 Example package MyRubySourceHandler; use strict; use Carp qw( croak ); use TAP::Parser::SourceHandler::Executable; use base 'TAP::Parser::SourceHandler::Executable'; # expect $handler->(['mytest.rb', 'cmdline', 'args']); sub make_iterator { my ($self, $source) = @_; my @test_args = @{ $source->test_args }; my $rb_file = $test_args[0]; croak("error: Ruby file '$rb_file' not found!") unless (-f $rb_file); return $self->SUPER::raw_source(['/usr/bin/ruby', @test_args]); } =head1 SEE ALSO L, L, L, L, L, L, L, L =cut SourceHandler/File.pm000064400000005661152347644500010541 0ustar00package TAP::Parser::SourceHandler::File; use strict; use warnings; use TAP::Parser::IteratorFactory (); use TAP::Parser::Iterator::Stream (); use base 'TAP::Parser::SourceHandler'; TAP::Parser::IteratorFactory->register_handler(__PACKAGE__); =head1 NAME TAP::Parser::SourceHandler::File - Stream TAP from a text file. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Source; use TAP::Parser::SourceHandler::File; my $source = TAP::Parser::Source->new->raw( \'file.tap' ); $source->assemble_meta; my $class = 'TAP::Parser::SourceHandler::File'; my $vote = $class->can_handle( $source ); my $iter = $class->make_iterator( $source ); =head1 DESCRIPTION This is a I L - it has 2 jobs: 1. Figure out if the I source it's given is a file containing raw TAP output. See L for more details. 2. Takes raw TAP from the text file given, and converts into an iterator. Unless you're writing a plugin or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C my $vote = $class->can_handle( $source ); Only votes if $source looks like a regular file. Casts the following votes: 0.9 if it's a .tap file 0.9 if it has an extension matching any given in user config. =cut sub can_handle { my ( $class, $src ) = @_; my $meta = $src->meta; my $config = $src->config_for($class); return 0 unless $meta->{is_file}; my $file = $meta->{file}; return 0.9 if $file->{lc_ext} eq '.tap'; if ( my $exts = $config->{extensions} ) { my @exts = ref $exts eq 'ARRAY' ? @$exts : $exts; return 0.9 if grep { lc($_) eq $file->{lc_ext} } @exts; } return 0; } =head3 C my $iterator = $class->make_iterator( $source ); Returns a new L for the source. Cs on error. =cut sub make_iterator { my ( $class, $source ) = @_; $class->_croak('$source->raw must be a scalar ref') unless $source->meta->{is_scalar}; my $file = ${ $source->raw }; my $fh; open( $fh, '<', $file ) or $class->_croak("error opening TAP source file '$file': $!"); return $class->iterator_class->new($fh); } =head3 C The class of iterator to use, override if you're sub-classing. Defaults to L. =cut use constant iterator_class => 'TAP::Parser::Iterator::Stream'; 1; __END__ =head1 CONFIGURATION { extensions => [ @case_insensitive_exts_to_match ] } =head1 SUBCLASSING Please see L for a subclassing overview. =head1 SEE ALSO L, L, L, L, L, L, L =cut Aggregator.pm000064400000022033152347644500007176 0ustar00package TAP::Parser::Aggregator; use strict; use warnings; use Benchmark; use base 'TAP::Object'; =head1 NAME TAP::Parser::Aggregator - Aggregate TAP::Parser results =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Aggregator; my $aggregate = TAP::Parser::Aggregator->new; $aggregate->add( 't/00-load.t', $load_parser ); $aggregate->add( 't/10-lex.t', $lex_parser ); my $summary = <<'END_SUMMARY'; Passed: %s Failed: %s Unexpectedly succeeded: %s END_SUMMARY printf $summary, scalar $aggregate->passed, scalar $aggregate->failed, scalar $aggregate->todo_passed; =head1 DESCRIPTION C collects parser objects and allows reporting/querying their aggregate results. =head1 METHODS =head2 Class Methods =head3 C my $aggregate = TAP::Parser::Aggregator->new; Returns a new C object. =cut # new() implementation supplied by TAP::Object my %SUMMARY_METHOD_FOR; BEGIN { # install summary methods %SUMMARY_METHOD_FOR = map { $_ => $_ } qw( failed parse_errors passed skipped todo todo_passed total wait exit ); $SUMMARY_METHOD_FOR{total} = 'tests_run'; $SUMMARY_METHOD_FOR{planned} = 'tests_planned'; for my $method ( keys %SUMMARY_METHOD_FOR ) { next if 'total' eq $method; no strict 'refs'; *$method = sub { my $self = shift; return wantarray ? @{ $self->{"descriptions_for_$method"} } : $self->{$method}; }; } } # end install summary methods sub _initialize { my ($self) = @_; $self->{parser_for} = {}; $self->{parse_order} = []; for my $summary ( keys %SUMMARY_METHOD_FOR ) { $self->{$summary} = 0; next if 'total' eq $summary; $self->{"descriptions_for_$summary"} = []; } return $self; } ############################################################################## =head2 Instance Methods =head3 C $aggregate->add( $description => $parser ); The C<$description> is usually a test file name (but only by convention.) It is used as a unique identifier (see e.g. L<"parsers">.) Reusing a description is a fatal error. The C<$parser> is a L object. =cut sub add { my ( $self, $description, $parser ) = @_; if ( exists $self->{parser_for}{$description} ) { $self->_croak( "You already have a parser for ($description)." . " Perhaps you have run the same test twice." ); } push @{ $self->{parse_order} } => $description; $self->{parser_for}{$description} = $parser; while ( my ( $summary, $method ) = each %SUMMARY_METHOD_FOR ) { # Slightly nasty. Instead we should maybe have 'cooked' accessors # for results that may be masked by the parser. next if ( $method eq 'exit' || $method eq 'wait' ) && $parser->ignore_exit; if ( my $count = $parser->$method() ) { $self->{$summary} += $count; push @{ $self->{"descriptions_for_$summary"} } => $description; } } return $self; } ############################################################################## =head3 C my $count = $aggregate->parsers; my @parsers = $aggregate->parsers; my @parsers = $aggregate->parsers(@descriptions); In scalar context without arguments, this method returns the number of parsers aggregated. In list context without arguments, returns the parsers in the order they were added. If C<@descriptions> is given, these correspond to the keys used in each call to the add() method. Returns an array of the requested parsers (in the requested order) in list context or an array reference in scalar context. Requesting an unknown identifier is a fatal error. =cut sub parsers { my $self = shift; return $self->_get_parsers(@_) if @_; my $descriptions = $self->{parse_order}; my @parsers = @{ $self->{parser_for} }{@$descriptions}; # Note: Because of the way context works, we must assign the parsers to # the @parsers array or else this method does not work as documented. return @parsers; } sub _get_parsers { my ( $self, @descriptions ) = @_; my @parsers; for my $description (@descriptions) { $self->_croak("A parser for ($description) could not be found") unless exists $self->{parser_for}{$description}; push @parsers => $self->{parser_for}{$description}; } return wantarray ? @parsers : \@parsers; } =head3 C Get an array of descriptions in the order in which they were added to the aggregator. =cut sub descriptions { @{ shift->{parse_order} || [] } } =head3 C Call C immediately before adding any results to the aggregator. Among other times it records the start time for the test run. =cut sub start { my $self = shift; $self->{start_time} = Benchmark->new; } =head3 C Call C immediately after adding all test results to the aggregator. =cut sub stop { my $self = shift; $self->{end_time} = Benchmark->new; } =head3 C Elapsed returns a L object that represents the running time of the aggregated tests. In order for C to be valid you must call C before running the tests and C immediately afterwards. =cut sub elapsed { my $self = shift; require Carp; Carp::croak q{Can't call elapsed without first calling start and then stop} unless defined $self->{start_time} && defined $self->{end_time}; return timediff( $self->{end_time}, $self->{start_time} ); } =head3 C Returns a formatted string representing the runtime returned by C. This lets the caller not worry about Benchmark. =cut sub elapsed_timestr { my $self = shift; my $elapsed = $self->elapsed; return timestr($elapsed); } =head3 C Return true if all the tests passed and no parse errors were detected. =cut sub all_passed { my $self = shift; return $self->total && $self->total == $self->passed && !$self->has_errors; } =head3 C Get a single word describing the status of the aggregated tests. Depending on the outcome of the tests returns 'PASS', 'FAIL' or 'NOTESTS'. This token is understood by L. =cut sub get_status { my $self = shift; my $total = $self->total; my $passed = $self->passed; return ( $self->has_errors || $total != $passed ) ? 'FAIL' : $total ? 'PASS' : 'NOTESTS'; } ############################################################################## =head2 Summary methods Each of the following methods will return the total number of corresponding tests if called in scalar context. If called in list context, returns the descriptions of the parsers which contain the corresponding tests (see C for an explanation of description. =over 4 =item * failed =item * parse_errors =item * passed =item * planned =item * skipped =item * todo =item * todo_passed =item * wait =item * exit =back For example, to find out how many tests unexpectedly succeeded (TODO tests which passed when they shouldn't): my $count = $aggregate->todo_passed; my @descriptions = $aggregate->todo_passed; Note that C and C are the totals of the wait and exit statuses of each of the tests. These values are totalled only to provide a true value if any of them are non-zero. =cut ############################################################################## =head3 C my $tests_run = $aggregate->total; Returns the total number of tests run. =cut sub total { shift->{total} } ############################################################################## =head3 C if ( $parser->has_problems ) { ... } Identical to C, but also returns true if any TODO tests unexpectedly succeeded. This is more akin to "warnings". =cut sub has_problems { my $self = shift; return $self->todo_passed || $self->has_errors; } ############################################################################## =head3 C if ( $parser->has_errors ) { ... } Returns true if I of the parsers failed. This includes: =over 4 =item * Failed tests =item * Parse errors =item * Bad exit or wait status =back =cut sub has_errors { my $self = shift; return $self->failed || $self->parse_errors || $self->exit || $self->wait; } ############################################################################## =head3 C # deprecated in favor of 'todo_passed'. This method was horribly misnamed. This was a badly misnamed method. It indicates which TODO tests unexpectedly succeeded. Will now issue a warning and call C. =cut sub todo_failed { warn '"todo_failed" is deprecated. Please use "todo_passed". See the docs.'; goto &todo_passed; } =head1 See Also L L =cut 1; ResultFactory.pm000064400000007741152347644500007733 0ustar00package TAP::Parser::ResultFactory; use strict; use warnings; use TAP::Parser::Result::Bailout (); use TAP::Parser::Result::Comment (); use TAP::Parser::Result::Plan (); use TAP::Parser::Result::Pragma (); use TAP::Parser::Result::Test (); use TAP::Parser::Result::Unknown (); use TAP::Parser::Result::Version (); use TAP::Parser::Result::YAML (); use base 'TAP::Object'; ############################################################################## =head1 NAME TAP::Parser::ResultFactory - Factory for creating TAP::Parser output objects =head1 SYNOPSIS use TAP::Parser::ResultFactory; my $token = {...}; my $factory = TAP::Parser::ResultFactory->new; my $result = $factory->make_result( $token ); =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head2 DESCRIPTION This is a simple factory class which returns a L subclass representing the current bit of test data from TAP (usually a single line). It is used primarily by L. Unless you're subclassing, you probably won't need to use this module directly. =head2 METHODS =head2 Class Methods =head3 C Creates a new factory class. I You currently don't need to instantiate a factory in order to use it. =head3 C Returns an instance the appropriate class for the test token passed in. my $result = TAP::Parser::ResultFactory->make_result($token); Can also be called as an instance method. =cut sub make_result { my ( $proto, $token ) = @_; my $type = $token->{type}; return $proto->class_for($type)->new($token); } =head3 C Takes one argument: C<$type>. Returns the class for this $type, or Cs with an error. =head3 C Takes two arguments: C<$type>, C<$class> This lets you override an existing type with your own custom type, or register a completely new type, eg: # create a custom result type: package MyResult; use strict; use base 'TAP::Parser::Result'; # register with the factory: TAP::Parser::ResultFactory->register_type( 'my_type' => __PACKAGE__ ); # use it: my $r = TAP::Parser::ResultFactory->( { type => 'my_type' } ); Your custom type should then be picked up automatically by the L. =cut our %CLASS_FOR = ( plan => 'TAP::Parser::Result::Plan', pragma => 'TAP::Parser::Result::Pragma', test => 'TAP::Parser::Result::Test', comment => 'TAP::Parser::Result::Comment', bailout => 'TAP::Parser::Result::Bailout', version => 'TAP::Parser::Result::Version', unknown => 'TAP::Parser::Result::Unknown', yaml => 'TAP::Parser::Result::YAML', ); sub class_for { my ( $class, $type ) = @_; # return target class: return $CLASS_FOR{$type} if exists $CLASS_FOR{$type}; # or complain: require Carp; Carp::croak("Could not determine class for result type '$type'"); } sub register_type { my ( $class, $type, $rclass ) = @_; # register it blindly, assume they know what they're doing $CLASS_FOR{$type} = $rclass; return $class; } 1; =head1 SUBCLASSING Please see L for a subclassing overview. There are a few things to bear in mind when creating your own C: =over 4 =item 1 The factory itself is never instantiated (this I change in the future). This means that C<_initialize> is never called. =item 2 Cnew> is never called, $tokens are reblessed. This I change in a future version! =item 3 L subclasses will register themselves with L directly: package MyFooResult; TAP::Parser::ResultFactory->register_type( foo => __PACKAGE__ ); Of course, it's up to you to decide whether or not to ignore them. =back =head2 Example package MyResultFactory; use strict; use MyResult; use base 'TAP::Parser::ResultFactory'; # force all results to be 'MyResult' sub class_for { return 'MyResult'; } 1; =head1 SEE ALSO L, L, L =cut Scheduler.pm000064400000026427152347644500007045 0ustar00package TAP::Parser::Scheduler; use strict; use warnings; use Carp; use TAP::Parser::Scheduler::Job; use TAP::Parser::Scheduler::Spinner; =head1 NAME TAP::Parser::Scheduler - Schedule tests during parallel testing =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Scheduler; =head1 DESCRIPTION =head1 METHODS =head2 Class Methods =head3 C my $sched = TAP::Parser::Scheduler->new(tests => \@tests); my $sched = TAP::Parser::Scheduler->new( tests => [ ['t/test_name.t','Test Description'], ... ], rules => \%rules, ); Given 'tests' and optional 'rules' as input, returns a new C object. Each member of C<@tests> should be either a a test file name, or a two element arrayref, where the first element is a test file name, and the second element is a test description. By default, we'll use the test name as the description. The optional C attribute provides direction on which tests should be run in parallel and which should be run sequentially. If no rule data structure is provided, a default data structure is used which makes every test eligible to be run in parallel: { par => '**' }, The rules data structure is documented more in the next section. =head2 Rules data structure The "C" data structure is the the heart of the scheduler. It allows you to express simple rules like "run all tests in sequence" or "run all tests in parallel except these five tests.". However, the rules structure also supports glob-style pattern matching and recursive definitions, so you can also express arbitarily complicated patterns. The rule must only have one top level key: either 'par' for "parallel" or 'seq' for "sequence". Values must be either strings with possible glob-style matching, or arrayrefs of strings or hashrefs which follow this pattern recursively. Every element in an arrayref directly below a 'par' key is eligible to be run in parallel, while vavalues directly below a 'seq' key must be run in sequence. =head3 Rules examples Here are some examples: # All tests be run in parallel (the default rule) { par => '**' }, # Run all tests in sequence, except those starting with "p" { par => 't/p*.t' }, # Run all tests in parallel, except those starting with "p" { seq => [ { seq => 't/p*.t' }, { par => '**' }, ], } # Run some startup tests in sequence, then some parallel tests then some # teardown tests in sequence. { seq => [ { seq => 't/startup/*.t' }, { par => ['t/a/*.t','t/b/*.t','t/c/*.t'], } { seq => 't/shutdown/*.t' }, ], }, =head3 Rules resolution =over 4 =item * By default, all tests are eligible to be run in parallel. Specifying any of your own rules removes this one. =item * "First match wins". The first rule that matches a test will be the one that applies. =item * Any test which does not match a rule will be run in sequence at the end of the run. =item * The existence of a rule does not imply selecting a test. You must still specify the tests to run. =item * Specifying a rule to allow tests to run in parallel does not make the run in parallel. You still need specify the number of parallel C in your Harness object. =back =head3 Glob-style pattern matching for rules We implement our own glob-style pattern matching. Here are the patterns it supports: ** is any number of characters, including /, within a pathname * is zero or more characters within a filename/directory name ? is exactly one character within a filename/directory name {foo,bar,baz} is any of foo, bar or baz. \ is an escape character =cut sub new { my $class = shift; croak "Need a number of key, value pairs" if @_ % 2; my %args = @_; my $tests = delete $args{tests} || croak "Need a 'tests' argument"; my $rules = delete $args{rules} || { par => '**' }; croak "Unknown arg(s): ", join ', ', sort keys %args if keys %args; # Turn any simple names into a name, description pair. TODO: Maybe # construct jobs here? my $self = bless {}, $class; $self->_set_rules( $rules, $tests ); return $self; } # Build the scheduler data structure. # # SCHEDULER-DATA ::= JOB # || ARRAY OF ARRAY OF SCHEDULER-DATA # # The nested arrays are the key to scheduling. The outer array contains # a list of things that may be executed in parallel. Whenever an # eligible job is sought any element of the outer array that is ready to # execute can be selected. The inner arrays represent sequential # execution. They can only proceed when the first job is ready to run. sub _set_rules { my ( $self, $rules, $tests ) = @_; # Convert all incoming tests to job objects. # If no test description is provided use the file name as the description. my @tests = map { TAP::Parser::Scheduler::Job->new(@$_) } map { 'ARRAY' eq ref $_ ? $_ : [ $_, $_ ] } @$tests; my $schedule = $self->_rule_clause( $rules, \@tests ); # If any tests are left add them as a sequential block at the end of # the run. $schedule = [ [ $schedule, @tests ] ] if @tests; $self->{schedule} = $schedule; } sub _rule_clause { my ( $self, $rule, $tests ) = @_; croak 'Rule clause must be a hash' unless 'HASH' eq ref $rule; my @type = keys %$rule; croak 'Rule clause must have exactly one key' unless @type == 1; my %handlers = ( par => sub { [ map { [$_] } @_ ]; }, seq => sub { [ [@_] ] }, ); my $handler = $handlers{ $type[0] } || croak 'Unknown scheduler type: ', $type[0]; my $val = $rule->{ $type[0] }; return $handler->( map { 'HASH' eq ref $_ ? $self->_rule_clause( $_, $tests ) : $self->_expand( $_, $tests ) } 'ARRAY' eq ref $val ? @$val : $val ); } sub _glob_to_regexp { my ( $self, $glob ) = @_; my $nesting; my $pattern; while (1) { if ( $glob =~ /\G\*\*/gc ) { # ** is any number of characters, including /, within a pathname $pattern .= '.*?'; } elsif ( $glob =~ /\G\*/gc ) { # * is zero or more characters within a filename/directory name $pattern .= '[^/]*'; } elsif ( $glob =~ /\G\?/gc ) { # ? is exactly one character within a filename/directory name $pattern .= '[^/]'; } elsif ( $glob =~ /\G\{/gc ) { # {foo,bar,baz} is any of foo, bar or baz. $pattern .= '(?:'; ++$nesting; } elsif ( $nesting and $glob =~ /\G,/gc ) { # , is only special inside {} $pattern .= '|'; } elsif ( $nesting and $glob =~ /\G\}/gc ) { # } that matches { is special. But unbalanced } are not. $pattern .= ')'; --$nesting; } elsif ( $glob =~ /\G(\\.)/gc ) { # A quoted literal $pattern .= $1; } elsif ( $glob =~ /\G([\},])/gc ) { # Sometimes meta characters $pattern .= '\\' . $1; } else { # Eat everything that is not a meta character. $glob =~ /\G([^{?*\\\},]*)/gc; $pattern .= quotemeta $1; } return $pattern if pos $glob == length $glob; } } sub _expand { my ( $self, $name, $tests ) = @_; my $pattern = $self->_glob_to_regexp($name); $pattern = qr/^ $pattern $/x; my @match = (); for ( my $ti = 0; $ti < @$tests; $ti++ ) { if ( $tests->[$ti]->filename =~ $pattern ) { push @match, splice @$tests, $ti, 1; $ti--; } } return @match; } =head2 Instance Methods =head3 C Get a list of all remaining tests. =cut sub get_all { my $self = shift; my @all = $self->_gather( $self->{schedule} ); $self->{count} = @all; @all; } sub _gather { my ( $self, $rule ) = @_; return unless defined $rule; return $rule unless 'ARRAY' eq ref $rule; return map { defined() ? $self->_gather($_) : () } map {@$_} @$rule; } =head3 C Return the next available job as L object or C if none are available. Returns a L if the scheduler still has pending jobs but none are available to run right now. =cut sub get_job { my $self = shift; $self->{count} ||= $self->get_all; my @jobs = $self->_find_next_job( $self->{schedule} ); if (@jobs) { --$self->{count}; return $jobs[0]; } return TAP::Parser::Scheduler::Spinner->new if $self->{count}; return; } sub _not_empty { my $ar = shift; return 1 unless 'ARRAY' eq ref $ar; for (@$ar) { return 1 if _not_empty($_); } return; } sub _is_empty { !_not_empty(@_) } sub _find_next_job { my ( $self, $rule ) = @_; my @queue = (); my $index = 0; while ( $index < @$rule ) { my $seq = $rule->[$index]; # Prune any exhausted items. shift @$seq while @$seq && _is_empty( $seq->[0] ); if (@$seq) { if ( defined $seq->[0] ) { if ( 'ARRAY' eq ref $seq->[0] ) { push @queue, $seq; } else { my $job = splice @$seq, 0, 1, undef; $job->on_finish( sub { shift @$seq } ); return $job; } } ++$index; } else { # Remove the empty sub-array from the array splice @$rule, $index, 1; } } for my $seq (@queue) { if ( my @jobs = $self->_find_next_job( $seq->[0] ) ) { return @jobs; } } return; } =head3 C Return a human readable representation of the scheduling tree. For example: my @tests = (qw{ t/startup/foo.t t/shutdown/foo.t t/a/foo.t t/b/foo.t t/c/foo.t t/d/foo.t }); my $sched = TAP::Parser::Scheduler->new( tests => \@tests, rules => { seq => [ { seq => 't/startup/*.t' }, { par => ['t/a/*.t','t/b/*.t','t/c/*.t'] }, { seq => 't/shutdown/*.t' }, ], }, ); Produces: par: seq: par: seq: par: seq: 't/startup/foo.t' par: seq: 't/a/foo.t' seq: 't/b/foo.t' seq: 't/c/foo.t' par: seq: 't/shutdown/foo.t' 't/d/foo.t' =cut sub as_string { my $self = shift; return $self->_as_string( $self->{schedule} ); } sub _as_string { my ( $self, $rule, $depth ) = ( shift, shift, shift || 0 ); my $pad = ' ' x 2; my $indent = $pad x $depth; if ( !defined $rule ) { return "$indent(undef)\n"; } elsif ( 'ARRAY' eq ref $rule ) { return unless @$rule; my $type = ( 'par', 'seq' )[ $depth % 2 ]; return join( '', "$indent$type:\n", map { $self->_as_string( $_, $depth + 1 ) } @$rule ); } else { return "$indent'" . $rule->filename . "'\n"; } } 1; IteratorFactory.pm000064400000020163152347644500010237 0ustar00package TAP::Parser::IteratorFactory; use strict; use warnings; use Carp qw( confess ); use File::Basename qw( fileparse ); use base 'TAP::Object'; use constant handlers => []; =head1 NAME TAP::Parser::IteratorFactory - Figures out which SourceHandler objects to use for a given Source =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::IteratorFactory; my $factory = TAP::Parser::IteratorFactory->new({ %config }); my $iterator = $factory->make_iterator( $filename ); =head1 DESCRIPTION This is a factory class that takes a L and runs it through all the registered Ls to see which one should handle the source. If you're a plugin author, you'll be interested in how to Ls, how L works. =head1 METHODS =head2 Class Methods =head3 C Creates a new factory class: my $sf = TAP::Parser::IteratorFactory->new( $config ); C<$config> is optional. If given, sets L and calls L. =cut sub _initialize { my ( $self, $config ) = @_; $self->config( $config || {} )->load_handlers; return $self; } =head3 C Registers a new L with this factory. __PACKAGE__->register_handler( $handler_class ); =head3 C List of handlers that have been registered. =cut sub register_handler { my ( $class, $dclass ) = @_; confess("$dclass must implement can_handle & make_iterator methods!") unless UNIVERSAL::can( $dclass, 'can_handle' ) && UNIVERSAL::can( $dclass, 'make_iterator' ); my $handlers = $class->handlers; push @{$handlers}, $dclass unless grep { $_ eq $dclass } @{$handlers}; return $class; } ############################################################################## =head2 Instance Methods =head3 C my $cfg = $sf->config; $sf->config({ Perl => { %config } }); Chaining getter/setter for the configuration of the available source handlers. This is a hashref keyed on handler class whose values contain config to be passed onto the handlers during detection & creation. Class names may be fully qualified or abbreviated, eg: # these are equivalent $sf->config({ 'TAP::Parser::SourceHandler::Perl' => { %config } }); $sf->config({ 'Perl' => { %config } }); =cut sub config { my $self = shift; return $self->{config} unless @_; unless ( 'HASH' eq ref $_[0] ) { $self->_croak('Argument to &config must be a hash reference'); } $self->{config} = shift; return $self; } sub _last_handler { my $self = shift; return $self->{last_handler} unless @_; $self->{last_handler} = shift; return $self; } sub _testing { my $self = shift; return $self->{testing} unless @_; $self->{testing} = shift; return $self; } ############################################################################## =head3 C $sf->load_handlers; Loads the handler classes defined in L. For example, given a config: $sf->config({ MySourceHandler => { some => 'config' }, }); C will attempt to load the C class by looking in C<@INC> for it in this order: TAP::Parser::SourceHandler::MySourceHandler MySourceHandler Cs on error. =cut sub load_handlers { my ($self) = @_; for my $handler ( keys %{ $self->config } ) { my $sclass = $self->_load_handler($handler); # TODO: store which class we loaded anywhere? } return $self; } sub _load_handler { my ( $self, $handler ) = @_; my @errors; for my $dclass ( "TAP::Parser::SourceHandler::$handler", $handler ) { return $dclass if UNIVERSAL::can( $dclass, 'can_handle' ) && UNIVERSAL::can( $dclass, 'make_iterator' ); eval "use $dclass"; if ( my $e = $@ ) { push @errors, $e; next; } return $dclass if UNIVERSAL::can( $dclass, 'can_handle' ) && UNIVERSAL::can( $dclass, 'make_iterator' ); push @errors, "handler '$dclass' does not implement can_handle & make_iterator"; } $self->_croak( "Cannot load handler '$handler': " . join( "\n", @errors ) ); } ############################################################################## =head3 C my $iterator = $src_factory->make_iterator( $source ); Given a L, finds the most suitable L to use to create a L (see L). Dies on error. =cut sub make_iterator { my ( $self, $source ) = @_; $self->_croak('no raw source defined!') unless defined $source->raw; $source->config( $self->config )->assemble_meta; # is the raw source already an object? return $source->raw if ( $source->meta->{is_object} && UNIVERSAL::isa( $source->raw, 'TAP::Parser::SourceHandler' ) ); # figure out what kind of source it is my $sd_class = $self->detect_source($source); $self->_last_handler($sd_class); return if $self->_testing; # create it my $iterator = $sd_class->make_iterator($source); return $iterator; } =head3 C Given a L, detects what kind of source it is and returns I L (the most confident one). Dies on error. The detection algorithm works something like this: for (@registered_handlers) { # ask them how confident they are about handling this source $confidence{$handler} = $handler->can_handle( $source ) } # choose the most confident handler Ties are handled by choosing the first handler. =cut sub detect_source { my ( $self, $source ) = @_; confess('no raw source ref defined!') unless defined $source->raw; # find a list of handlers that can handle this source: my %confidence_for; for my $handler ( @{ $self->handlers } ) { my $confidence = $handler->can_handle($source); # warn "handler: $handler: $confidence\n"; $confidence_for{$handler} = $confidence if $confidence; } if ( !%confidence_for ) { # error: can't detect source my $raw_source_short = substr( ${ $source->raw }, 0, 50 ); confess("Cannot detect source of '$raw_source_short'!"); return; } # if multiple handlers can handle it, choose the most confident one my @handlers = sort { $confidence_for{$b} <=> $confidence_for{$a} } keys %confidence_for; # Check for a tie. if( @handlers > 1 && $confidence_for{$handlers[0]} == $confidence_for{$handlers[1]} ) { my $filename = $source->meta->{file}{basename}; die("There is a tie between $handlers[0] and $handlers[1].\n". "Both voted $confidence_for{$handlers[0]} on $filename.\n"); } # this is really useful for debugging handlers: if ( $ENV{TAP_HARNESS_SOURCE_FACTORY_VOTES} ) { warn( "votes: ", join( ', ', map {"$_: $confidence_for{$_}"} @handlers ), "\n" ); } # return 1st return $handlers[0]; } 1; __END__ =head1 SUBCLASSING Please see L for a subclassing overview. =head2 Example If we've done things right, you'll probably want to write a new source, rather than sub-classing this (see L for that). But in case you find the need to... package MyIteratorFactory; use strict; use base 'TAP::Parser::IteratorFactory'; # override source detection algorithm sub detect_source { my ($self, $raw_source_ref, $meta) = @_; # do detective work, using $meta and whatever else... } 1; =head1 AUTHORS Steve Purkis =head1 ATTRIBUTION Originally ripped off from L. Moved out of L & converted to a factory class to support extensible TAP source detective work by Steve Purkis. =head1 SEE ALSO L, L, L, L, L, L, L, L =cut Iterator.pm000064400000005666152347644500006722 0ustar00package TAP::Parser::Iterator; use strict; use warnings; use base 'TAP::Object'; =head1 NAME TAP::Parser::Iterator - Base class for TAP source iterators =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS # to subclass: use TAP::Parser::Iterator (); use base 'TAP::Parser::Iterator'; sub _initialize { # see TAP::Object... } sub next_raw { ... } sub wait { ... } sub exit { ... } =head1 DESCRIPTION This is a simple iterator base class that defines L's iterator API. Iterators are typically created from Ls. =head1 METHODS =head2 Class Methods =head3 C Create an iterator. Provided by L. =head2 Instance Methods =head3 C while ( my $item = $iter->next ) { ... } Iterate through it, of course. =head3 C B this method is abstract and should be overridden. while ( my $item = $iter->next_raw ) { ... } Iterate raw input without applying any fixes for quirky input syntax. =cut sub next { my $self = shift; my $line = $self->next_raw; # vms nit: When encountering 'not ok', vms often has the 'not' on a line # by itself: # not # ok 1 - 'I hate VMS' if ( defined($line) and $line =~ /^\s*not\s*$/ ) { $line .= ( $self->next_raw || '' ); } return $line; } sub next_raw { require Carp; my $msg = Carp::longmess('abstract method called directly!'); $_[0]->_croak($msg); } =head3 C If necessary switch the input stream to handle unicode. This only has any effect for I/O handle based streams. The default implementation does nothing. =cut sub handle_unicode { } =head3 C Return a list of filehandles that may be used upstream in a select() call to signal that this Iterator is ready. Iterators that are not handle-based should return an empty list. The default implementation does nothing. =cut sub get_select_handles { return; } =head3 C B this method is abstract and should be overridden. my $wait_status = $iter->wait; Return the C status for this iterator. =head3 C B this method is abstract and should be overridden. my $wait_status = $iter->exit; Return the C status for this iterator. =cut sub wait { require Carp; my $msg = Carp::longmess('abstract method called directly!'); $_[0]->_croak($msg); } sub exit { require Carp; my $msg = Carp::longmess('abstract method called directly!'); $_[0]->_croak($msg); } 1; =head1 SUBCLASSING Please see L for a subclassing overview. You must override the abstract methods as noted above. =head2 Example L is probably the easiest example to follow. There's not much point repeating it here. =head1 SEE ALSO L, L, L, L, L, =cut Result/YAML.pm000064400000001560152347644500007136 0ustar00package TAP::Parser::Result::YAML; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::YAML - YAML result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a YAML block is encountered. 1..1 ok 1 - woo hooo! C<1..1> is the plan. Gotta have a plan. =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =item * C =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_yaml ) { print $result->data; } Return the parsed YAML data for this result =cut sub data { shift->{data} } 1; Result/Unknown.pm000064400000001336152347644500010034 0ustar00package TAP::Parser::Result::Unknown; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Unknown - Unknown result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if the parser does not recognize the token line. For example: 1..5 VERSION 7 ok 1 - woo hooo! ... woo hooo! is cool! In the above "TAP", the second and fourth lines will generate "Unknown" tokens. =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =item * C =back =cut 1; Result/Plan.pm000064400000004000152347644500007256 0ustar00package TAP::Parser::Result::Plan; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Plan - Plan result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a plan line is encountered. 1..1 ok 1 - woo hooo! C<1..1> is the plan. Gotta have a plan. =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =item * C =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_plan ) { print $result->plan; } This is merely a synonym for C. =cut sub plan { '1..' . shift->{tests_planned} } ############################################################################## =head3 C my $planned = $result->tests_planned; Returns the number of tests planned. For example, a plan of C<1..17> will cause this method to return '17'. =cut sub tests_planned { shift->{tests_planned} } ############################################################################## =head3 C my $directive = $plan->directive; If a SKIP directive is included with the plan, this method will return it. 1..0 # SKIP: why bother? =cut sub directive { shift->{directive} } ############################################################################## =head3 C if ( $result->has_skip ) { ... } Returns a boolean value indicating whether or not this test has a SKIP directive. =head3 C my $explanation = $plan->explanation; If a SKIP directive was included with the plan, this method will return the explanation, if any. =cut sub explanation { shift->{explanation} } =head3 C my $todo = $result->todo_list; for ( @$todo ) { ... } =cut sub todo_list { shift->{todo_list} } 1; Result/Pragma.pm000064400000001662152347644500007606 0ustar00package TAP::Parser::Result::Pragma; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Pragma - TAP pragma token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a pragma is encountered. TAP version 13 pragma +strict, -foo Pragmas are only supported from TAP version 13 onwards. =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =item * C =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_pragma ) { @pragmas = $result->pragmas; } =cut sub pragmas { my @pragmas = @{ shift->{pragmas} }; return wantarray ? @pragmas : \@pragmas; } 1; Result/Comment.pm000064400000001732152347644500007777 0ustar00package TAP::Parser::Result::Comment; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Comment - Comment result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a comment line is encountered. 1..1 ok 1 - woo hooo! # this is a comment =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C Note that this method merely returns the comment preceded by a '# '. =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_comment ) { my $comment = $result->comment; print "I have something to say: $comment"; } =cut sub comment { shift->{comment} } sub as_string { shift->{raw} } 1; Result/Test.pm000064400000013676152347644500007326 0ustar00package TAP::Parser::Result::Test; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Test - Test result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a test line is encountered. 1..1 ok 1 - woo hooo! =head1 OVERRIDDEN METHODS This class is the workhorse of the L system. Most TAP lines will be test lines and if C<< $result->is_test >>, then you have a bunch of methods at your disposal. =head2 Instance Methods =cut ############################################################################## =head3 C my $ok = $result->ok; Returns the literal text of the C or C status. =cut sub ok { shift->{ok} } ############################################################################## =head3 C my $test_number = $result->number; Returns the number of the test, even if the original TAP output did not supply that number. =cut sub number { shift->{test_num} } sub _number { my ( $self, $number ) = @_; $self->{test_num} = $number; } ############################################################################## =head3 C my $description = $result->description; Returns the description of the test, if any. This is the portion after the test number but before the directive. =cut sub description { shift->{description} } ############################################################################## =head3 C my $directive = $result->directive; Returns either C or C if either directive was present for a test line. =cut sub directive { shift->{directive} } ############################################################################## =head3 C my $explanation = $result->explanation; If a test had either a C or C directive, this method will return the accompanying explanation, if present. not ok 17 - 'Pigs can fly' # TODO not enough acid For the above line, the explanation is I. =cut sub explanation { shift->{explanation} } ############################################################################## =head3 C if ( $result->is_ok ) { ... } Returns a boolean value indicating whether or not the test passed. Remember that for TODO tests, the test always passes. If the test is unplanned, this method will always return false. See C. =cut sub is_ok { my $self = shift; return if $self->is_unplanned; # TODO directives reverse the sense of a test. return $self->has_todo ? 1 : $self->ok !~ /not/; } ############################################################################## =head3 C if ( $result->is_actual_ok ) { ... } Returns a boolean value indicating whether or not the test passed, regardless of its TODO status. =cut sub is_actual_ok { my $self = shift; return $self->{ok} !~ /not/; } ############################################################################## =head3 C Deprecated. Please use C instead. =cut sub actual_passed { warn 'actual_passed() is deprecated. Please use "is_actual_ok()"'; goto &is_actual_ok; } ############################################################################## =head3 C if ( $test->todo_passed ) { # test unexpectedly succeeded } If this is a TODO test and an 'ok' line, this method returns true. Otherwise, it will always return false (regardless of passing status on non-todo tests). This is used to track which tests unexpectedly succeeded. =cut sub todo_passed { my $self = shift; return $self->has_todo && $self->is_actual_ok; } ############################################################################## =head3 C # deprecated in favor of 'todo_passed'. This method was horribly misnamed. This was a badly misnamed method. It indicates which TODO tests unexpectedly succeeded. Will now issue a warning and call C. =cut sub todo_failed { warn 'todo_failed() is deprecated. Please use "todo_passed()"'; goto &todo_passed; } ############################################################################## =head3 C if ( $result->has_skip ) { ... } Returns a boolean value indicating whether or not this test has a SKIP directive. =head3 C if ( $result->has_todo ) { ... } Returns a boolean value indicating whether or not this test has a TODO directive. =head3 C print $result->as_string; This method prints the test as a string. It will probably be similar, but not necessarily identical, to the original test line. Directives are capitalized, some whitespace may be trimmed and a test number will be added if it was not present in the original line. If you need the original text of the test line, use the C method. =cut sub as_string { my $self = shift; my $string = $self->ok . " " . $self->number; if ( my $description = $self->description ) { $string .= " $description"; } if ( my $directive = $self->directive ) { my $explanation = $self->explanation; $string .= " # $directive $explanation"; } return $string; } ############################################################################## =head3 C if ( $test->is_unplanned ) { ... } $test->is_unplanned(1); If a test number is greater than the number of planned tests, this method will return true. Unplanned tests will I return false for C, regardless of whether or not the test C. Note that if tests have a trailing plan, it is not possible to set this property for unplanned tests as we do not know it's unplanned until the plan is reached: print <<'END'; ok 1 ok 2 1..1 END =cut sub is_unplanned { my $self = shift; return ( $self->{unplanned} || '' ) unless @_; $self->{unplanned} = !!shift; return $self; } 1; Result/Version.pm000064400000001662152347644500010024 0ustar00package TAP::Parser::Result::Version; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Version - TAP syntax version token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a version line is encountered. TAP version 13 ok 1 not ok 2 The first version of TAP to include an explicit version number is 13. =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =item * C =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_version ) { print $result->version; } This is merely a synonym for C. =cut sub version { shift->{version} } 1; Result/Bailout.pm000064400000002174152347644500007775 0ustar00package TAP::Parser::Result::Bailout; use strict; use warnings; use base 'TAP::Parser::Result'; =head1 NAME TAP::Parser::Result::Bailout - Bailout result token. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 DESCRIPTION This is a subclass of L. A token of this class will be returned if a bail out line is encountered. 1..5 ok 1 - woo hooo! Bail out! Well, so much for "woo hooo!" =head1 OVERRIDDEN METHODS Mainly listed here to shut up the pitiful screams of the pod coverage tests. They keep me awake at night. =over 4 =item * C =back =cut ############################################################################## =head2 Instance Methods =head3 C if ( $result->is_bailout ) { my $explanation = $result->explanation; print "We bailed out because ($explanation)"; } If, and only if, a token is a bailout token, you can get an "explanation" via this method. The explanation is the text after the mystical "Bail out!" words which appear in the tap output. =cut sub explanation { shift->{bailout} } sub as_string { shift->{bailout} } 1; SourceHandler.pm000064400000012042152347644500007651 0ustar00package TAP::Parser::SourceHandler; use strict; use warnings; use TAP::Parser::Iterator (); use base 'TAP::Object'; =head1 NAME TAP::Parser::SourceHandler - Base class for different TAP source handlers =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS # abstract class - don't use directly! # see TAP::Parser::IteratorFactory for general usage # must be sub-classed for use package MySourceHandler; use base 'TAP::Parser::SourceHandler'; sub can_handle { return $confidence_level } sub make_iterator { return $iterator } # see example below for more details =head1 DESCRIPTION This is an abstract base class for L handlers / handlers. A C does whatever is necessary to produce & capture a stream of TAP from the I source, and package it up in a L for the parser to consume. C must implement the I interface used by L. At 2 methods, the interface is pretty simple: L and L. Unless you're writing a new L, a plugin, or subclassing L, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C I. my $vote = $class->can_handle( $source ); C<$source> is a L. Returns a number between C<0> & C<1> reflecting how confidently the raw source can be handled. For example, C<0> means the source cannot handle it, C<0.5> means it may be able to, and C<1> means it definitely can. See L for details on how this is used. =cut sub can_handle { my ( $class, $args ) = @_; $class->_croak( "Abstract method 'can_handle' not implemented for $class!"); return; } =head3 C I. my $iterator = $class->make_iterator( $source ); C<$source> is a L. Returns a new L object for use by the L. Cs on error. =cut sub make_iterator { my ( $class, $args ) = @_; $class->_croak( "Abstract method 'make_iterator' not implemented for $class!"); return; } 1; __END__ =head1 SUBCLASSING Please see L for a subclassing overview, and any of the subclasses that ship with this module as an example. What follows is a quick overview. Start by familiarizing yourself with L and L. L is the easiest sub-class to use as an example. It's important to point out that if you want your subclass to be automatically used by L you'll have to and make sure it gets loaded somehow. If you're using L you can write an L plugin. If you're using L or L directly (e.g. through a custom script, L, or L) you can use the C option which will cause L to load your subclass). Don't forget to register your class with L. =head2 Example package MySourceHandler; use strict; use MySourceHandler; # see TAP::Parser::SourceHandler use TAP::Parser::IteratorFactory; use base 'TAP::Parser::SourceHandler'; TAP::Parser::IteratorFactory->register_handler( __PACKAGE__ ); sub can_handle { my ( $class, $src ) = @_; my $meta = $src->meta; my $config = $src->config_for( $class ); if ($config->{accept_all}) { return 1.0; } elsif (my $file = $meta->{file}) { return 0.0 unless $file->{exists}; return 1.0 if $file->{lc_ext} eq '.tap'; return 0.9 if $file->{shebang} && $file->{shebang} =~ /^#!.+tap/; return 0.5 if $file->{text}; return 0.1 if $file->{binary}; } elsif ($meta->{scalar}) { return 0.8 if $$raw_source_ref =~ /\d\.\.\d/; return 0.6 if $meta->{has_newlines}; } elsif ($meta->{array}) { return 0.8 if $meta->{size} < 5; return 0.6 if $raw_source_ref->[0] =~ /foo/; return 0.5; } elsif ($meta->{hash}) { return 0.6 if $raw_source_ref->{foo}; return 0.2; } return 0; } sub make_iterator { my ($class, $source) = @_; # this is where you manipulate the source and # capture the stream of TAP in an iterator # either pick a TAP::Parser::Iterator::* or write your own... my $iterator = TAP::Parser::Iterator::Array->new([ 'foo', 'bar' ]); return $iterator; } 1; =head1 AUTHORS TAPx Developers. Source detection stuff added by Steve Purkis =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L =cut Multiplexer.pm000064400000010251152347644500007425 0ustar00package TAP::Parser::Multiplexer; use strict; use warnings; use IO::Select; use base 'TAP::Object'; use constant IS_WIN32 => $^O =~ /^(MS)?Win32$/; use constant IS_VMS => $^O eq 'VMS'; use constant SELECT_OK => !( IS_VMS || IS_WIN32 ); =head1 NAME TAP::Parser::Multiplexer - Multiplex multiple TAP::Parsers =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Multiplexer; my $mux = TAP::Parser::Multiplexer->new; $mux->add( $parser1, $stash1 ); $mux->add( $parser2, $stash2 ); while ( my ( $parser, $stash, $result ) = $mux->next ) { # do stuff } =head1 DESCRIPTION C gathers input from multiple TAP::Parsers. Internally it calls select on the input file handles for those parsers to wait for one or more of them to have input available. See L for an example of its use. =head1 METHODS =head2 Class Methods =head3 C my $mux = TAP::Parser::Multiplexer->new; Returns a new C object. =cut # new() implementation supplied by TAP::Object sub _initialize { my $self = shift; $self->{select} = IO::Select->new; $self->{avid} = []; # Parsers that can't select $self->{count} = 0; return $self; } ############################################################################## =head2 Instance Methods =head3 C $mux->add( $parser, $stash ); Add a TAP::Parser to the multiplexer. C<$stash> is an optional opaque reference that will be returned from C along with the parser and the next result. =cut sub add { my ( $self, $parser, $stash ) = @_; if ( SELECT_OK && ( my @handles = $parser->get_select_handles ) ) { my $sel = $self->{select}; # We have to turn handles into file numbers here because by # the time we want to remove them from our IO::Select they # will already have been closed by the iterator. my @filenos = map { fileno $_ } @handles; for my $h (@handles) { $sel->add( [ $h, $parser, $stash, @filenos ] ); } $self->{count}++; } else { push @{ $self->{avid} }, [ $parser, $stash ]; } } =head3 C my $count = $mux->parsers; Returns the number of parsers. Parsers are removed from the multiplexer when their input is exhausted. =cut sub parsers { my $self = shift; return $self->{count} + scalar @{ $self->{avid} }; } sub _iter { my $self = shift; my $sel = $self->{select}; my $avid = $self->{avid}; my @ready = (); return sub { # Drain all the non-selectable parsers first if (@$avid) { my ( $parser, $stash ) = @{ $avid->[0] }; my $result = $parser->next; shift @$avid unless defined $result; return ( $parser, $stash, $result ); } unless (@ready) { return unless $sel->count; @ready = $sel->can_read; } my ( $h, $parser, $stash, @handles ) = @{ shift @ready }; my $result = $parser->next; unless ( defined $result ) { $sel->remove(@handles); $self->{count}--; # Force another can_read - we may now have removed a handle # thought to have been ready. @ready = (); } return ( $parser, $stash, $result ); }; } =head3 C Return a result from the next available parser. Returns a list containing the parser from which the result came, the stash that corresponds with that parser and the result. my ( $parser, $stash, $result ) = $mux->next; If C<$result> is undefined the corresponding parser has reached the end of its input (and will automatically be removed from the multiplexer). When all parsers are exhausted an empty list will be returned. if ( my ( $parser, $stash, $result ) = $mux->next ) { if ( ! defined $result ) { # End of this parser } else { # Process result } } else { # All parsers finished } =cut sub next { my $self = shift; return ( $self->{_iter} ||= $self->_iter )->(); } =head1 See Also L L =cut 1; Grammar.pm000064400000036462152347644500006515 0ustar00package TAP::Parser::Grammar; use strict; use warnings; use TAP::Parser::ResultFactory (); use TAP::Parser::YAMLish::Reader (); use base 'TAP::Object'; =head1 NAME TAP::Parser::Grammar - A grammar for the Test Anything Protocol. =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Grammar; my $grammar = $self->make_grammar({ iterator => $tap_parser_iterator, parser => $tap_parser, version => 12, }); my $result = $grammar->tokenize; =head1 DESCRIPTION C tokenizes lines from a L and constructs L subclasses to represent the tokens. Do not attempt to use this class directly. It won't make sense. It's mainly here to ensure that we will be able to have pluggable grammars when TAP is expanded at some future date (plus, this stuff was really cluttering the parser). =head1 METHODS =head2 Class Methods =head3 C my $grammar = TAP::Parser::Grammar->new({ iterator => $iterator, parser => $parser, version => $version, }); Returns L grammar object that will parse the TAP stream from the specified iterator. Both C and C are required arguments. If C is not set it defaults to C<12> (see L for more details). =cut # new() implementation supplied by TAP::Object sub _initialize { my ( $self, $args ) = @_; $self->{iterator} = $args->{iterator}; # TODO: accessor $self->{iterator} ||= $args->{stream}; # deprecated $self->{parser} = $args->{parser}; # TODO: accessor $self->set_version( $args->{version} || 12 ); return $self; } my %language_for; { # XXX the 'not' and 'ok' might be on separate lines in VMS ... my $ok = qr/(?:not )?ok\b/; my $num = qr/\d+/; my %v12 = ( version => { syntax => qr/^TAP\s+version\s+(\d+)\s*\z/i, handler => sub { my ( $self, $line ) = @_; my $version = $1; return $self->_make_version_token( $line, $version, ); }, }, plan => { syntax => qr/^1\.\.(\d+)\s*(.*)\z/, handler => sub { my ( $self, $line ) = @_; my ( $tests_planned, $tail ) = ( $1, $2 ); my $explanation = undef; my $skip = ''; if ( $tail =~ /^todo((?:\s+\d+)+)/ ) { my @todo = split /\s+/, _trim($1); return $self->_make_plan_token( $line, $tests_planned, 'TODO', '', \@todo ); } elsif ( 0 == $tests_planned ) { $skip = 'SKIP'; # If we can't match # SKIP the directive should be undef. ($explanation) = $tail =~ /^#\s*SKIP\S*\s+(.*)/i; } elsif ( $tail !~ /^\s*$/ ) { return $self->_make_unknown_token($line); } $explanation = '' unless defined $explanation; return $self->_make_plan_token( $line, $tests_planned, $skip, $explanation, [] ); }, }, # An optimization to handle the most common test lines without # directives. simple_test => { syntax => qr/^($ok) \ ($num) (?:\ ([^#]+))? \z/x, handler => sub { my ( $self, $line ) = @_; my ( $ok, $num, $desc ) = ( $1, $2, $3 ); return $self->_make_test_token( $line, $ok, $num, $desc ); }, }, test => { syntax => qr/^($ok) \s* ($num)? \s* (.*) \z/x, handler => sub { my ( $self, $line ) = @_; my ( $ok, $num, $desc ) = ( $1, $2, $3 ); my ( $dir, $explanation ) = ( '', '' ); if ($desc =~ m/^ ( [^\\\#]* (?: \\. [^\\\#]* )* ) \# \s* (SKIP|TODO) \b \s* (.*) $/ix ) { ( $desc, $dir, $explanation ) = ( $1, $2, $3 ); } return $self->_make_test_token( $line, $ok, $num, $desc, $dir, $explanation ); }, }, comment => { syntax => qr/^#(.*)/, handler => sub { my ( $self, $line ) = @_; my $comment = $1; return $self->_make_comment_token( $line, $comment ); }, }, bailout => { syntax => qr/^\s*Bail out!\s*(.*)/, handler => sub { my ( $self, $line ) = @_; my $explanation = $1; return $self->_make_bailout_token( $line, $explanation ); }, }, ); my %v13 = ( %v12, plan => { syntax => qr/^1\.\.(\d+)\s*(?:\s*#\s*SKIP\b(.*))?\z/i, handler => sub { my ( $self, $line ) = @_; my ( $tests_planned, $explanation ) = ( $1, $2 ); my $skip = ( 0 == $tests_planned || defined $explanation ) ? 'SKIP' : ''; $explanation = '' unless defined $explanation; return $self->_make_plan_token( $line, $tests_planned, $skip, $explanation, [] ); }, }, yaml => { syntax => qr/^ (\s+) (---.*) $/x, handler => sub { my ( $self, $line ) = @_; my ( $pad, $marker ) = ( $1, $2 ); return $self->_make_yaml_token( $pad, $marker ); }, }, pragma => { syntax => qr/^ pragma \s+ ( [-+] \w+ \s* (?: , \s* [-+] \w+ \s* )* ) $/x, handler => sub { my ( $self, $line ) = @_; my $pragmas = $1; return $self->_make_pragma_token( $line, $pragmas ); }, }, ); %language_for = ( '12' => { tokens => \%v12, }, '13' => { tokens => \%v13, setup => sub { shift->{iterator}->handle_unicode; }, }, ); } ############################################################################## =head2 Instance Methods =head3 C $grammar->set_version(13); Tell the grammar which TAP syntax version to support. The lowest supported version is 12. Although 'TAP version' isn't valid version 12 syntax it is accepted so that higher version numbers may be parsed. =cut sub set_version { my $self = shift; my $version = shift; if ( my $language = $language_for{$version} ) { $self->{version} = $version; $self->{tokens} = $language->{tokens}; if ( my $setup = $language->{setup} ) { $self->$setup(); } $self->_order_tokens; } else { require Carp; Carp::croak("Unsupported syntax version: $version"); } } # Optimization to put the most frequent tokens first. sub _order_tokens { my $self = shift; my %copy = %{ $self->{tokens} }; my @ordered_tokens = grep {defined} map { delete $copy{$_} } qw( simple_test test comment plan ); push @ordered_tokens, values %copy; $self->{ordered_tokens} = \@ordered_tokens; } ############################################################################## =head3 C my $token = $grammar->tokenize; This method will return a L object representing the current line of TAP. =cut sub tokenize { my $self = shift; my $line = $self->{iterator}->next; unless ( defined $line ) { delete $self->{parser}; # break circular ref return; } my $token; for my $token_data ( @{ $self->{ordered_tokens} } ) { if ( $line =~ $token_data->{syntax} ) { my $handler = $token_data->{handler}; $token = $self->$handler($line); last; } } $token = $self->_make_unknown_token($line) unless $token; return $self->{parser}->make_result($token); } ############################################################################## =head3 C my @types = $grammar->token_types; Returns the different types of tokens which this grammar can parse. =cut sub token_types { my $self = shift; return keys %{ $self->{tokens} }; } ############################################################################## =head3 C my $syntax = $grammar->syntax_for($token_type); Returns a pre-compiled regular expression which will match a chunk of TAP corresponding to the token type. For example (not that you should really pay attention to this, C<< $grammar->syntax_for('comment') >> will return C<< qr/^#(.*)/ >>. =cut sub syntax_for { my ( $self, $type ) = @_; return $self->{tokens}->{$type}->{syntax}; } ############################################################################## =head3 C my $handler = $grammar->handler_for($token_type); Returns a code reference which, when passed an appropriate line of TAP, returns the lexed token corresponding to that line. As a result, the basic TAP parsing loop looks similar to the following: my @tokens; my $grammar = TAP::Grammar->new; LINE: while ( defined( my $line = $parser->_next_chunk_of_tap ) ) { for my $type ( $grammar->token_types ) { my $syntax = $grammar->syntax_for($type); if ( $line =~ $syntax ) { my $handler = $grammar->handler_for($type); push @tokens => $grammar->$handler($line); next LINE; } } push @tokens => $grammar->_make_unknown_token($line); } =cut sub handler_for { my ( $self, $type ) = @_; return $self->{tokens}->{$type}->{handler}; } sub _make_version_token { my ( $self, $line, $version ) = @_; return { type => 'version', raw => $line, version => $version, }; } sub _make_plan_token { my ( $self, $line, $tests_planned, $directive, $explanation, $todo ) = @_; if ( $directive eq 'SKIP' && 0 != $tests_planned && $self->{version} < 13 ) { warn "Specified SKIP directive in plan but more than 0 tests ($line)\n"; } return { type => 'plan', raw => $line, tests_planned => $tests_planned, directive => $directive, explanation => _trim($explanation), todo_list => $todo, }; } sub _make_test_token { my ( $self, $line, $ok, $num, $desc, $dir, $explanation ) = @_; return { ok => $ok, # forcing this to be an integer (and not a string) reduces memory # consumption. RT #84939 test_num => ( defined $num ? 0 + $num : undef ), description => _trim($desc), directive => ( defined $dir ? uc $dir : '' ), explanation => _trim($explanation), raw => $line, type => 'test', }; } sub _make_unknown_token { my ( $self, $line ) = @_; return { raw => $line, type => 'unknown', }; } sub _make_comment_token { my ( $self, $line, $comment ) = @_; return { type => 'comment', raw => $line, comment => _trim($comment) }; } sub _make_bailout_token { my ( $self, $line, $explanation ) = @_; return { type => 'bailout', raw => $line, bailout => _trim($explanation) }; } sub _make_yaml_token { my ( $self, $pad, $marker ) = @_; my $yaml = TAP::Parser::YAMLish::Reader->new; my $iterator = $self->{iterator}; # Construct a reader that reads from our input stripping leading # spaces from each line. my $leader = length($pad); my $strip = qr{ ^ (\s{$leader}) (.*) $ }x; my @extra = ($marker); my $reader = sub { return shift @extra if @extra; my $line = $iterator->next; return $2 if $line =~ $strip; return; }; my $data = $yaml->read($reader); # Reconstitute input. This is convoluted. Maybe we should just # record it on the way in... chomp( my $raw = $yaml->get_raw ); $raw =~ s/^/$pad/mg; return { type => 'yaml', raw => $raw, data => $data }; } sub _make_pragma_token { my ( $self, $line, $pragmas ) = @_; return { type => 'pragma', raw => $line, pragmas => [ split /\s*,\s*/, _trim($pragmas) ], }; } sub _trim { my $data = shift; return '' unless defined $data; $data =~ s/^\s+//; $data =~ s/\s+$//; return $data; } 1; =head1 TAP GRAMMAR B This grammar is slightly out of date. There's still some discussion about it and a new one will be provided when we have things better defined. The L does not use a formal grammar because TAP is essentially a stream-based protocol. In fact, it's quite legal to have an infinite stream. For the same reason that we don't apply regexes to streams, we're not using a formal grammar here. Instead, we parse the TAP in lines. For purposes for forward compatibility, any result which does not match the following grammar is currently referred to as L. It is I a parse error. A formal grammar would look similar to the following: (* For the time being, I'm cheating on the EBNF by allowing certain terms to be defined by POSIX character classes by using the following syntax: digit ::= [:digit:] As far as I am aware, that's not valid EBNF. Sue me. I didn't know how to write "char" otherwise (Unicode issues). Suggestions welcome. *) tap ::= version? { comment | unknown } leading_plan lines | lines trailing_plan {comment} version ::= 'TAP version ' positiveInteger {positiveInteger} "\n" leading_plan ::= plan skip_directive? "\n" trailing_plan ::= plan "\n" plan ::= '1..' nonNegativeInteger lines ::= line {line} line ::= (comment | test | unknown | bailout ) "\n" test ::= status positiveInteger? description? directive? status ::= 'not '? 'ok ' description ::= (character - (digit | '#')) {character - '#'} directive ::= todo_directive | skip_directive todo_directive ::= hash_mark 'TODO' ' ' {character} skip_directive ::= hash_mark 'SKIP' ' ' {character} comment ::= hash_mark {character} hash_mark ::= '#' {' '} bailout ::= 'Bail out!' {character} unknown ::= { (character - "\n") } (* POSIX character classes and other terminals *) digit ::= [:digit:] character ::= ([:print:] - "\n") positiveInteger ::= ( digit - '0' ) {digit} nonNegativeInteger ::= digit {digit} =head1 SUBCLASSING Please see L for a subclassing overview. If you I want to subclass L's grammar the best thing to do is read through the code. There's no easy way of summarizing it here. =head1 SEE ALSO L, L, L, L, =cut YAMLish/Writer.pm000064400000012163152347644500007641 0ustar00package TAP::Parser::YAMLish::Writer; use strict; use warnings; use base 'TAP::Object'; our $VERSION = '3.42'; my $ESCAPE_CHAR = qr{ [ \x00-\x1f \" ] }x; my $ESCAPE_KEY = qr{ (?: ^\W ) | $ESCAPE_CHAR }x; my @UNPRINTABLE = qw( z x01 x02 x03 x04 x05 x06 a x08 t n v f r x0e x0f x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x1a e x1c x1d x1e x1f ); # new() implementation supplied by TAP::Object sub write { my $self = shift; die "Need something to write" unless @_; my $obj = shift; my $out = shift || \*STDOUT; die "Need a reference to something I can write to" unless ref $out; $self->{writer} = $self->_make_writer($out); $self->_write_obj( '---', $obj ); $self->_put('...'); delete $self->{writer}; } sub _make_writer { my $self = shift; my $out = shift; my $ref = ref $out; if ( 'CODE' eq $ref ) { return $out; } elsif ( 'ARRAY' eq $ref ) { return sub { push @$out, shift }; } elsif ( 'SCALAR' eq $ref ) { return sub { $$out .= shift() . "\n" }; } elsif ( 'GLOB' eq $ref || 'IO::Handle' eq $ref ) { return sub { print $out shift(), "\n" }; } die "Can't write to $out"; } sub _put { my $self = shift; $self->{writer}->( join '', @_ ); } sub _enc_scalar { my $self = shift; my $val = shift; my $rule = shift; return '~' unless defined $val; if ( $val =~ /$rule/ ) { $val =~ s/\\/\\\\/g; $val =~ s/"/\\"/g; $val =~ s/ ( [\x00-\x1f] ) / '\\' . $UNPRINTABLE[ ord($1) ] /gex; return qq{"$val"}; } if ( length($val) == 0 or $val =~ /\s/ ) { $val =~ s/'/''/; return "'$val'"; } return $val; } sub _write_obj { my $self = shift; my $prefix = shift; my $obj = shift; my $indent = shift || 0; if ( my $ref = ref $obj ) { my $pad = ' ' x $indent; if ( 'HASH' eq $ref ) { if ( keys %$obj ) { $self->_put($prefix); for my $key ( sort keys %$obj ) { my $value = $obj->{$key}; $self->_write_obj( $pad . $self->_enc_scalar( $key, $ESCAPE_KEY ) . ':', $value, $indent + 1 ); } } else { $self->_put( $prefix, ' {}' ); } } elsif ( 'ARRAY' eq $ref ) { if (@$obj) { $self->_put($prefix); for my $value (@$obj) { $self->_write_obj( $pad . '-', $value, $indent + 1 ); } } else { $self->_put( $prefix, ' []' ); } } else { die "Don't know how to encode $ref"; } } else { $self->_put( $prefix, ' ', $self->_enc_scalar( $obj, $ESCAPE_CHAR ) ); } } 1; __END__ =pod =head1 NAME TAP::Parser::YAMLish::Writer - Write YAMLish data =head1 VERSION Version 3.42 =head1 SYNOPSIS use TAP::Parser::YAMLish::Writer; my $data = { one => 1, two => 2, three => [ 1, 2, 3 ], }; my $yw = TAP::Parser::YAMLish::Writer->new; # Write to an array... $yw->write( $data, \@some_array ); # ...an open file handle... $yw->write( $data, $some_file_handle ); # ...a string ... $yw->write( $data, \$some_string ); # ...or a closure $yw->write( $data, sub { my $line = shift; print "$line\n"; } ); =head1 DESCRIPTION Encodes a scalar, hash reference or array reference as YAMLish. =head1 METHODS =head2 Class Methods =head3 C my $writer = TAP::Parser::YAMLish::Writer->new; The constructor C creates and returns an empty C object. =head2 Instance Methods =head3 C $writer->write($obj, $output ); Encode a scalar, hash reference or array reference as YAML. my $writer = sub { my $line = shift; print SOMEFILE "$line\n"; }; my $data = { one => 1, two => 2, three => [ 1, 2, 3 ], }; my $yw = TAP::Parser::YAMLish::Writer->new; $yw->write( $data, $writer ); The C< $output > argument may be: =over =item * a reference to a scalar to append YAML to =item * the handle of an open file =item * a reference to an array into which YAML will be pushed =item * a code reference =back If you supply a code reference the subroutine will be called once for each line of output with the line as its only argument. Passed lines will have no trailing newline. =head1 AUTHOR Andy Armstrong, =head1 SEE ALSO L, L, L, L, L, L =head1 COPYRIGHT Copyright 2007-2011 Andy Armstrong. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. =cut YAMLish/Reader.pm000064400000016663152347644500007600 0ustar00package TAP::Parser::YAMLish::Reader; use strict; use warnings; use base 'TAP::Object'; our $VERSION = '3.42'; # TODO: # Handle blessed object syntax # Printable characters for escapes my %UNESCAPES = ( z => "\x00", a => "\x07", t => "\x09", n => "\x0a", v => "\x0b", f => "\x0c", r => "\x0d", e => "\x1b", '\\' => '\\', ); my $QQ_STRING = qr{ " (?:\\. | [^"])* " }x; my $HASH_LINE = qr{ ^ ($QQ_STRING|\S+) \s* : \s* (?: (.+?) \s* )? $ }x; my $IS_HASH_KEY = qr{ ^ [\w\'\"] }x; my $IS_END_YAML = qr{ ^ \.\.\. \s* $ }x; my $IS_QQ_STRING = qr{ ^ $QQ_STRING $ }x; # new() implementation supplied by TAP::Object sub read { my $self = shift; my $obj = shift; die "Must have a code reference to read input from" unless ref $obj eq 'CODE'; $self->{reader} = $obj; $self->{capture} = []; # Prime the reader $self->_next; return unless $self->{next}; my $doc = $self->_read; # The terminator is mandatory otherwise we'd consume a line from the # iterator that doesn't belong to us. If we want to remove this # restriction we'll have to implement look-ahead in the iterators. # Which might not be a bad idea. my $dots = $self->_peek; die "Missing '...' at end of YAMLish" unless defined $dots and $dots =~ $IS_END_YAML; delete $self->{reader}; delete $self->{next}; return $doc; } sub get_raw { join( "\n", grep defined, @{ shift->{capture} || [] } ) . "\n" } sub _peek { my $self = shift; return $self->{next} unless wantarray; my $line = $self->{next}; $line =~ /^ (\s*) (.*) $ /x; return ( $2, length $1 ); } sub _next { my $self = shift; die "_next called with no reader" unless $self->{reader}; my $line = $self->{reader}->(); $self->{next} = $line; push @{ $self->{capture} }, $line; } sub _read { my $self = shift; my $line = $self->_peek; # Do we have a document header? if ( $line =~ /^ --- (?: \s* (.+?)? \s* )? $/x ) { $self->_next; return $self->_read_scalar($1) if defined $1; # Inline? my ( $next, $indent ) = $self->_peek; if ( $next =~ /^ - /x ) { return $self->_read_array($indent); } elsif ( $next =~ $IS_HASH_KEY ) { return $self->_read_hash( $next, $indent ); } elsif ( $next =~ $IS_END_YAML ) { die "Premature end of YAMLish"; } else { die "Unsupported YAMLish syntax: '$next'"; } } else { die "YAMLish document header not found"; } } # Parse a double quoted string sub _read_qq { my $self = shift; my $str = shift; unless ( $str =~ s/^ " (.*?) " $/$1/x ) { die "Internal: not a quoted string"; } $str =~ s/\\"/"/gx; $str =~ s/ \\ ( [tartan\\favez] | x([0-9a-fA-F]{2}) ) / (length($1) > 1) ? pack("H2", $2) : $UNESCAPES{$1} /gex; return $str; } # Parse a scalar string to the actual scalar sub _read_scalar { my $self = shift; my $string = shift; return undef if $string eq '~'; return {} if $string eq '{}'; return [] if $string eq '[]'; if ( $string eq '>' || $string eq '|' ) { my ( $line, $indent ) = $self->_peek; die "Multi-line scalar content missing" unless defined $line; my @multiline = ($line); while (1) { $self->_next; my ( $next, $ind ) = $self->_peek; last if $ind < $indent; my $pad = $string eq '|' ? ( ' ' x ( $ind - $indent ) ) : ''; push @multiline, $pad . $next; } return join( ( $string eq '>' ? ' ' : "\n" ), @multiline ) . "\n"; } if ( $string =~ /^ ' (.*) ' $/x ) { ( my $rv = $1 ) =~ s/''/'/g; return $rv; } if ( $string =~ $IS_QQ_STRING ) { return $self->_read_qq($string); } if ( $string =~ /^['"]/ ) { # A quote with folding... we don't support that die __PACKAGE__ . " does not support multi-line quoted scalars"; } # Regular unquoted string return $string; } sub _read_nested { my $self = shift; my ( $line, $indent ) = $self->_peek; if ( $line =~ /^ -/x ) { return $self->_read_array($indent); } elsif ( $line =~ $IS_HASH_KEY ) { return $self->_read_hash( $line, $indent ); } else { die "Unsupported YAMLish syntax: '$line'"; } } # Parse an array sub _read_array { my ( $self, $limit ) = @_; my $ar = []; while (1) { my ( $line, $indent ) = $self->_peek; last if $indent < $limit || !defined $line || $line =~ $IS_END_YAML; if ( $indent > $limit ) { die "Array line over-indented"; } if ( $line =~ /^ (- \s+) \S+ \s* : (?: \s+ | $ ) /x ) { $indent += length $1; $line =~ s/-\s+//; push @$ar, $self->_read_hash( $line, $indent ); } elsif ( $line =~ /^ - \s* (.+?) \s* $/x ) { die "Unexpected start of YAMLish" if $line =~ /^---/; $self->_next; push @$ar, $self->_read_scalar($1); } elsif ( $line =~ /^ - \s* $/x ) { $self->_next; push @$ar, $self->_read_nested; } elsif ( $line =~ $IS_HASH_KEY ) { $self->_next; push @$ar, $self->_read_hash( $line, $indent, ); } else { die "Unsupported YAMLish syntax: '$line'"; } } return $ar; } sub _read_hash { my ( $self, $line, $limit ) = @_; my $indent; my $hash = {}; while (1) { die "Badly formed hash line: '$line'" unless $line =~ $HASH_LINE; my ( $key, $value ) = ( $self->_read_scalar($1), $2 ); $self->_next; if ( defined $value ) { $hash->{$key} = $self->_read_scalar($value); } else { $hash->{$key} = $self->_read_nested; } ( $line, $indent ) = $self->_peek; last if $indent < $limit || !defined $line || $line =~ $IS_END_YAML; } return $hash; } 1; __END__ =pod =head1 NAME TAP::Parser::YAMLish::Reader - Read YAMLish data from iterator =head1 VERSION Version 3.42 =head1 SYNOPSIS =head1 DESCRIPTION Note that parts of this code were derived from L with the permission of Adam Kennedy. =head1 METHODS =head2 Class Methods =head3 C The constructor C creates and returns an empty C object. my $reader = TAP::Parser::YAMLish::Reader->new; =head2 Instance Methods =head3 C my $got = $reader->read($iterator); Read YAMLish from a L and return the data structure it represents. =head3 C my $source = $reader->get_source; Return the raw YAMLish source from the most recent C. =head1 AUTHOR Andy Armstrong, Adam Kennedy wrote L which provided the template and many of the YAML matching regular expressions for this module. =head1 SEE ALSO L, L, L, L, L, L =head1 COPYRIGHT Copyright 2007-2011 Andy Armstrong. Portions copyright 2006-2008 Adam Kennedy. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. =cut Iterator/Stream.pm000064400000003605152347644500010144 0ustar00package TAP::Parser::Iterator::Stream; use strict; use warnings; use base 'TAP::Parser::Iterator'; =head1 NAME TAP::Parser::Iterator::Stream - Iterator for filehandle-based TAP sources =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Iterator::Stream; open( TEST, 'test.tap' ); my $it = TAP::Parser::Iterator::Stream->new(\*TEST); my $line = $it->next; =head1 DESCRIPTION This is a simple iterator wrapper for reading from filehandles, used by L. Unless you're writing a plugin or subclassing, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C Create an iterator. Expects one argument containing a filehandle. =cut # new() implementation supplied by TAP::Object sub _initialize { my ( $self, $thing ) = @_; $self->{fh} = $thing; return $self; } =head2 Instance Methods =head3 C Iterate through it, of course. =head3 C Iterate raw input without applying any fixes for quirky input syntax. =head3 C Get the wait status for this iterator. Always returns zero. =head3 C Get the exit status for this iterator. Always returns zero. =cut sub wait { shift->exit } sub exit { shift->{fh} ? () : 0 } sub next_raw { my $self = shift; my $fh = $self->{fh}; if ( defined( my $line = <$fh> ) ) { chomp $line; return $line; } else { $self->_finish; return; } } sub _finish { my $self = shift; close delete $self->{fh}; } sub get_select_handles { my $self = shift; # return our handle in case it's a socket or pipe (select()-able) return ( $self->{fh}, ) if (-S $self->{fh} || -p $self->{fh}); return; } 1; =head1 ATTRIBUTION Originally ripped off from L. =head1 SEE ALSO L, L, L, =cut Iterator/Array.pm000064400000003240152347644500007762 0ustar00package TAP::Parser::Iterator::Array; use strict; use warnings; use base 'TAP::Parser::Iterator'; =head1 NAME TAP::Parser::Iterator::Array - Iterator for array-based TAP sources =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Iterator::Array; my @data = ('foo', 'bar', baz'); my $it = TAP::Parser::Iterator::Array->new(\@data); my $line = $it->next; =head1 DESCRIPTION This is a simple iterator wrapper for arrays of scalar content, used by L. Unless you're writing a plugin or subclassing, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C Create an iterator. Takes one argument: an C<$array_ref> =head2 Instance Methods =head3 C Iterate through it, of course. =head3 C Iterate raw input without applying any fixes for quirky input syntax. =head3 C Get the wait status for this iterator. For an array iterator this will always be zero. =head3 C Get the exit status for this iterator. For an array iterator this will always be zero. =cut # new() implementation supplied by TAP::Object sub _initialize { my ( $self, $thing ) = @_; chomp @$thing; $self->{idx} = 0; $self->{array} = $thing; $self->{exit} = undef; return $self; } sub wait { shift->exit } sub exit { my $self = shift; return 0 if $self->{idx} >= @{ $self->{array} }; return; } sub next_raw { my $self = shift; return $self->{array}->[ $self->{idx}++ ]; } 1; =head1 ATTRIBUTION Originally ripped off from L. =head1 SEE ALSO L, L, L, =cut Iterator/Process.pm000064400000021634152347644500010331 0ustar00package TAP::Parser::Iterator::Process; use strict; use warnings; use Config; use IO::Handle; use base 'TAP::Parser::Iterator'; my $IS_WIN32 = ( $^O =~ /^(MS)?Win32$/ ); =head1 NAME TAP::Parser::Iterator::Process - Iterator for process-based TAP sources =head1 VERSION Version 3.42 =cut our $VERSION = '3.42'; =head1 SYNOPSIS use TAP::Parser::Iterator::Process; my %args = ( command => ['python', 'setup.py', 'test'], merge => 1, setup => sub { ... }, teardown => sub { ... }, ); my $it = TAP::Parser::Iterator::Process->new(\%args); my $line = $it->next; =head1 DESCRIPTION This is a simple iterator wrapper for executing external processes, used by L. Unless you're writing a plugin or subclassing, you probably won't need to use this module directly. =head1 METHODS =head2 Class Methods =head3 C Create an iterator. Expects one argument containing a hashref of the form: command => \@command_to_execute merge => $attempt_merge_stderr_and_stdout? setup => $callback_to_setup_command teardown => $callback_to_teardown_command Tries to uses L & L to communicate with the spawned process if they are available. Falls back onto C. =head2 Instance Methods =head3 C Iterate through the process output, of course. =head3 C Iterate raw input without applying any fixes for quirky input syntax. =head3 C Get the wait status for this iterator's process. =head3 C Get the exit status for this iterator's process. =cut { no warnings 'uninitialized'; # get around a catch22 in the test suite that causes failures on Win32: local $SIG{__DIE__} = undef; eval { require POSIX; &POSIX::WEXITSTATUS(0) }; if ($@) { *_wait2exit = sub { $_[1] >> 8 }; } else { *_wait2exit = sub { POSIX::WEXITSTATUS( $_[1] ) } } } sub _use_open3 { my $self = shift; return unless $Config{d_fork} || $IS_WIN32; for my $module (qw( IPC::Open3 IO::Select )) { eval "use $module"; return if $@; } return 1; } { my $got_unicode; sub _get_unicode { return $got_unicode if defined $got_unicode; eval 'use Encode qw(decode_utf8);'; $got_unicode = $@ ? 0 : 1; } } # new() implementation supplied by TAP::Object sub _initialize { my ( $self, $args ) = @_; my @command = @{ delete $args->{command} || [] } or die "Must supply a command to execute"; $self->{command} = [@command]; # Private. Used to frig with chunk size during testing. my $chunk_size = delete $args->{_chunk_size} || 65536; my $merge = delete $args->{merge}; my ( $pid, $err, $sel ); if ( my $setup = delete $args->{setup} ) { $setup->(@command); } my $out = IO::Handle->new; if ( $self->_use_open3 ) { # HOTPATCH {{{ my $xclose = \&IPC::Open3::xclose; no warnings; local *IPC::Open3::xclose = sub { my $fh = shift; no strict 'refs'; return if ( fileno($fh) == fileno(STDIN) ); $xclose->($fh); }; # }}} if ($IS_WIN32) { $err = $merge ? '' : '>&STDERR'; eval { $pid = open3( '<&STDIN', $out, $merge ? '' : $err, @command ); }; die "Could not execute (@command): $@" if $@; if ( $] >= 5.006 ) { binmode($out, ":crlf"); } } else { $err = $merge ? '' : IO::Handle->new; eval { $pid = open3( '<&STDIN', $out, $err, @command ); }; die "Could not execute (@command): $@" if $@; $sel = $merge ? undef : IO::Select->new( $out, $err ); } } else { $err = ''; my $command = join( ' ', map { $_ =~ /\s/ ? qq{"$_"} : $_ } @command ); open( $out, "$command|" ) or die "Could not execute ($command): $!"; } $self->{out} = $out; $self->{err} = $err; $self->{sel} = $sel; $self->{pid} = $pid; $self->{exit} = undef; $self->{chunk_size} = $chunk_size; if ( my $teardown = delete $args->{teardown} ) { $self->{teardown} = sub { $teardown->(@command); }; } return $self; } =head3 C Upgrade the input stream to handle UTF8. =cut sub handle_unicode { my $self = shift; if ( $self->{sel} ) { if ( _get_unicode() ) { # Make sure our iterator has been constructed and... my $next = $self->{_next} ||= $self->_next; # ...wrap it to do UTF8 casting $self->{_next} = sub { my $line = $next->(); return decode_utf8($line) if defined $line; return; }; } } else { if ( $] >= 5.008 ) { eval 'binmode($self->{out}, ":utf8")'; } } } ############################################################################## sub wait { shift->{wait} } sub exit { shift->{exit} } sub _next { my $self = shift; if ( my $out = $self->{out} ) { if ( my $sel = $self->{sel} ) { my $err = $self->{err}; my @buf = (); my $partial = ''; # Partial line my $chunk_size = $self->{chunk_size}; return sub { return shift @buf if @buf; READ: while ( my @ready = $sel->can_read ) { for my $fh (@ready) { my $got = sysread $fh, my ($chunk), $chunk_size; if ( $got == 0 ) { $sel->remove($fh); } elsif ( $fh == $err ) { print STDERR $chunk; # echo STDERR } else { $chunk = $partial . $chunk; $partial = ''; # Make sure we have a complete line unless ( substr( $chunk, -1, 1 ) eq "\n" ) { my $nl = rindex $chunk, "\n"; if ( $nl == -1 ) { $partial = $chunk; redo READ; } else { $partial = substr( $chunk, $nl + 1 ); $chunk = substr( $chunk, 0, $nl ); } } push @buf, split /\n/, $chunk; return shift @buf if @buf; } } } # Return partial last line if ( length $partial ) { my $last = $partial; $partial = ''; return $last; } $self->_finish; return; }; } else { return sub { if ( defined( my $line = <$out> ) ) { chomp $line; return $line; } $self->_finish; return; }; } } else { return sub { $self->_finish; return; }; } } sub next_raw { my $self = shift; return ( $self->{_next} ||= $self->_next )->(); } sub _finish { my $self = shift; my $status = $?; # Avoid circular refs $self->{_next} = sub {return} if $] >= 5.006; # If we have a subprocess we need to wait for it to terminate if ( defined $self->{pid} ) { if ( $self->{pid} == waitpid( $self->{pid}, 0 ) ) { $status = $?; } } ( delete $self->{out} )->close if $self->{out}; # If we have an IO::Select we also have an error handle to close. if ( $self->{sel} ) { ( delete $self->{err} )->close; delete $self->{sel}; } else { $status = $?; } # Sometimes we get -1 on Windows. Presumably that means status not # available. $status = 0 if $IS_WIN32 && $status == -1; $self->{wait} = $status; $self->{exit} = $self->_wait2exit($status); if ( my $teardown = $self->{teardown} ) { $teardown->(); } return $self; } =head3 C Return a list of filehandles that may be used upstream in a select() call to signal that this Iterator is ready. Iterators that are not handle based should return an empty list. =cut sub get_select_handles { my $self = shift; return grep $_, ( $self->{out}, $self->{err} ); } 1; =head1 ATTRIBUTION Originally ripped off from L. =head1 SEE ALSO L, L, L, =cut